mirror of
https://github.com/Z3Prover/z3
synced 2025-04-05 09:04:07 +00:00
integrate lambda expressions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bf4edef761
commit
520ce9a5ee
|
@ -27,6 +27,7 @@ Version 4.8.0
|
|||
Use sat.acce=true to enable the full repertoire of inprocessing methods. By default, clauses that are "eliminated" by acce are tagged
|
||||
as lemmas (redundant) and are garbage collected if their glue level is high.
|
||||
- Substantial overhaul of the spacer horn clause engine.
|
||||
- Added basic features to support Lambda expressions.
|
||||
|
||||
- Removed features:
|
||||
- interpolation API
|
||||
|
|
|
@ -47,6 +47,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select(c, a, i);
|
||||
|
@ -99,6 +100,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store(c, a, i, v);
|
||||
|
@ -155,6 +157,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_map(Z3_context c, Z3_func_decl f, unsigned n, Z3_ast const* args) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_map(c, f, n, args);
|
||||
|
|
|
@ -808,8 +808,7 @@ extern "C" {
|
|||
expr * a = to_expr(_a);
|
||||
expr * const * to = to_exprs(_to);
|
||||
var_subst subst(m, false);
|
||||
expr_ref new_a(m);
|
||||
subst(a, num_exprs, to, new_a);
|
||||
expr_ref new_a = subst(a, num_exprs, to);
|
||||
mk_c(c)->save_ast_trail(new_a);
|
||||
RETURN_Z3(of_expr(new_a.get()));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
|
@ -910,6 +909,7 @@ extern "C" {
|
|||
case PR_TRANSITIVITY_STAR: return Z3_OP_PR_TRANSITIVITY_STAR;
|
||||
case PR_MONOTONICITY: return Z3_OP_PR_MONOTONICITY;
|
||||
case PR_QUANT_INTRO: return Z3_OP_PR_QUANT_INTRO;
|
||||
case PR_BIND: return Z3_OP_PR_BIND;
|
||||
case PR_DISTRIBUTIVITY: return Z3_OP_PR_DISTRIBUTIVITY;
|
||||
case PR_AND_ELIM: return Z3_OP_PR_AND_ELIM;
|
||||
case PR_NOT_OR_ELIM: return Z3_OP_PR_NOT_OR_ELIM;
|
||||
|
|
|
@ -173,6 +173,7 @@ extern "C" {
|
|||
to_optimize_ptr(o)->get_model(_m);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref, *mk_c(c));
|
||||
if (_m) {
|
||||
if (mk_c(c)->params().m_model_compress) _m->compress();
|
||||
m_ref->m_model = _m;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -90,7 +90,7 @@ extern "C" {
|
|||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls > 0) {
|
||||
result = mk_c(c)->m().mk_quantifier(
|
||||
(0 != is_forall),
|
||||
is_forall ? forall_k : exists_k,
|
||||
names.size(), ts, names.c_ptr(), to_expr(body),
|
||||
weight,
|
||||
qid,
|
||||
|
@ -144,6 +144,61 @@ extern "C" {
|
|||
return Z3_mk_quantifier(c, 0, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lambda(Z3_context c,
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_lambda(c, num_decls, types, decl_names, body);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(types);
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
names.push_back(to_symbol(decl_names[i]));
|
||||
}
|
||||
result = mk_c(c)->m().mk_lambda(names.size(), ts, names.c_ptr(), to_expr(body));
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||
unsigned num_decls, Z3_app const vars[],
|
||||
Z3_ast body) {
|
||||
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_lambda_const(c, num_decls, vars, body);
|
||||
RESET_ERROR_CODE();
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
|
||||
svector<symbol> _names;
|
||||
ptr_vector<sort> _vars;
|
||||
ptr_vector<expr> _args;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
app* a = to_app(vars[i]);
|
||||
_names.push_back(to_app(a)->get_decl()->get_name());
|
||||
_args.push_back(a);
|
||||
_vars.push_back(mk_c(c)->m().get_sort(a));
|
||||
}
|
||||
expr_ref result(mk_c(c)->m());
|
||||
expr_abstract(mk_c(c)->m(), 0, num_decls, _args.c_ptr(), to_expr(body), result);
|
||||
|
||||
result = mk_c(c)->m().mk_lambda(_vars.size(), _vars.c_ptr(), _names.c_ptr(), result);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
|
@ -292,17 +347,27 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_forall(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->is_forall();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return ::is_forall(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_quantifier_exists(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_exists(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return ::is_exists(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_lambda(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_lambda(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return ::is_lambda(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_weight(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_weight(c, a);
|
||||
|
@ -485,3 +550,4 @@ extern "C" {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -433,6 +433,9 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
if (_m) {
|
||||
if (mk_c(c)->params().m_model_compress) _m->compress();
|
||||
}
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref, *mk_c(c));
|
||||
m_ref->m_model = _m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
|
|
|
@ -252,7 +252,6 @@ namespace z3 {
|
|||
*/
|
||||
sort array_sort(sort d, sort r);
|
||||
sort array_sort(sort_vector const& d, sort r);
|
||||
|
||||
/**
|
||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
||||
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||
|
@ -675,7 +674,21 @@ namespace z3 {
|
|||
\brief Return true if this expression is a quantifier.
|
||||
*/
|
||||
bool is_quantifier() const { return kind() == Z3_QUANTIFIER_AST; }
|
||||
|
||||
/**
|
||||
\brief Return true if this expression is a universal quantifier.
|
||||
*/
|
||||
bool is_forall() const { return 0 != Z3_is_quantifier_forall(ctx(), m_ast); }
|
||||
/**
|
||||
\brief Return true if this expression is an existential quantifier.
|
||||
*/
|
||||
bool is_exists() const { return 0 != Z3_is_quantifier_exists(ctx(), m_ast); }
|
||||
/**
|
||||
\brief Return true if this expression is a lambda expression.
|
||||
*/
|
||||
bool is_lambda() const { return 0 != Z3_is_lambda(ctx(), m_ast); }
|
||||
/**
|
||||
|
||||
\brief Return true if this expression is a variable.
|
||||
*/
|
||||
bool is_var() const { return kind() == Z3_VAR_AST; }
|
||||
|
@ -1638,6 +1651,31 @@ namespace z3 {
|
|||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 1, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 2, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 3, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 4, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr_vector const & xs, expr const & b) {
|
||||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), vars.size(), vars.ptr(), b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr pble(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
|
@ -2521,7 +2559,6 @@ namespace z3 {
|
|||
array<Z3_sort> dom(d);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
}
|
||||
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
for (unsigned i = 0; i < n; i++) { _enum_names[i] = Z3_mk_string_symbol(*this, enum_names[i]); }
|
||||
|
@ -2785,12 +2822,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, int i) { return select(a, a.ctx().num_val(i, a.get_sort().array_domain())); }
|
||||
inline expr store(expr const & a, expr const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
Z3_ast r = Z3_mk_store(a.ctx(), a, i, v);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
|
@ -2800,6 +2833,13 @@ namespace z3 {
|
|||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr store(expr const & a, expr const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
Z3_ast r = Z3_mk_store(a.ctx(), a, i, v);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr store(expr const & a, int i, expr const & v) { return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), v); }
|
||||
inline expr store(expr const & a, expr i, int v) { return store(a, i, a.ctx().num_val(v, a.get_sort().array_range())); }
|
||||
inline expr store(expr const & a, int i, int v) {
|
||||
|
|
|
@ -37,6 +37,6 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Contract.Requires(ctx != null);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
|||
IntNum.cs
|
||||
IntSort.cs
|
||||
IntSymbol.cs
|
||||
Lambda.cs
|
||||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
|
|
|
@ -3292,6 +3292,53 @@ namespace Microsoft.Z3
|
|||
return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a lambda expression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a lambda expression.
|
||||
/// <paramref name="sorts"/> is an array
|
||||
/// with the sorts of the bound variables, <paramref name="names"/> is an array with the
|
||||
/// 'names' of the bound variables, and <paramref name="body"/> is the body of the
|
||||
/// lambda.
|
||||
/// Note that the bound variables are de-Bruijn indices created using <see cref="MkBound"/>.
|
||||
/// Z3 applies the convention that the last element in <paramref name="names"/> and
|
||||
/// <paramref name="sorts"/> refers to the variable with index 0, the second to last element
|
||||
/// of <paramref name="names"/> and <paramref name="sorts"/> refers to the variable
|
||||
/// with index 1, etc.
|
||||
/// </remarks>
|
||||
/// <param name="sorts">the sorts of the bound variables.</param>
|
||||
/// <param name="names">names of the bound variables</param>
|
||||
/// <param name="body">the body of the quantifier.</param>
|
||||
public Lambda MkLambda(Sort[] sorts, Symbol[] names, Expr body)
|
||||
{
|
||||
Contract.Requires(sorts != null);
|
||||
Contract.Requires(names != null);
|
||||
Contract.Requires(body != null);
|
||||
Contract.Requires(sorts.Length == names.Length);
|
||||
Contract.Requires(Contract.ForAll(sorts, s => s != null));
|
||||
Contract.Requires(Contract.ForAll(names, n => n != null));
|
||||
Contract.Ensures(Contract.Result<Lambda>() != null);
|
||||
return new Lambda(this, sorts, names, body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a lambda expression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a lambda expression using a list of constants that will
|
||||
/// form the set of bound variables.
|
||||
/// <seealso cref="MkLambda(Sort[], Symbol[], Expr)"/>
|
||||
/// </remarks>
|
||||
public Lambda MkLambda(Expr[] boundConstants, Expr body)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
Contract.Requires(boundConstants != null && Contract.ForAll(boundConstants, b => b != null));
|
||||
Contract.Ensures(Contract.Result<Lambda>() != null);
|
||||
return new Lambda(this, boundConstants, body);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion // Expr
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public bool IsExistential
|
||||
{
|
||||
get { return !IsUniversal; }
|
||||
get { return Native.Z3_is_quantifier_exists(Context.nCtx, NativeObject) != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -141,6 +141,7 @@ set(Z3_JAVA_JAR_SOURCE_FILES
|
|||
IntNum.java
|
||||
IntSort.java
|
||||
IntSymbol.java
|
||||
Lambda.java
|
||||
ListSort.java
|
||||
Log.java
|
||||
ModelDecRefQueue.java
|
||||
|
|
|
@ -518,7 +518,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Creates a fresh constant function declaration with a name prefixed with
|
||||
* {@code prefix"}.
|
||||
* {@code prefix}.
|
||||
* @see #mkFuncDecl(String,Sort,Sort)
|
||||
* @see #mkFuncDecl(String,Sort[],Sort)
|
||||
**/
|
||||
|
@ -696,7 +696,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates the equality {@code x"/> = <paramref name="y}.
|
||||
* Creates the equality {@code x = y}
|
||||
**/
|
||||
public BoolExpr mkEq(Expr x, Expr y)
|
||||
{
|
||||
|
@ -2498,6 +2498,40 @@ public class Context implements AutoCloseable {
|
|||
quantifierID, skolemID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lambda expression.
|
||||
*
|
||||
* {@code sorts} is an array
|
||||
* with the sorts of the bound variables, {@code names} is an array with the
|
||||
* 'names' of the bound variables, and {@code body} is the body of the
|
||||
* lambda.
|
||||
* Note that the bound variables are de-Bruijn indices created using {@see #MkBound}
|
||||
* Z3 applies the convention that the last element in {@code names} and
|
||||
* {@code sorts} refers to the variable with index 0, the second to last element
|
||||
* of {@code names} and {@code sorts} refers to the variable
|
||||
* with index 1, etc.
|
||||
*
|
||||
* @param sorts the sorts of the bound variables.
|
||||
* @param names names of the bound variables.
|
||||
* @param body the body of the quantifier.
|
||||
**/
|
||||
public Lambda mkLambda(Sort[] sorts, Symbol[] names, Expr body)
|
||||
{
|
||||
return Lambda.of(this, sorts, names, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lambda expression.
|
||||
*
|
||||
* Creates a lambda expression using a list of constants that will
|
||||
* form the set of bound variables.
|
||||
**/
|
||||
public Lambda mkLambda(Expr[] boundConstants, Expr body)
|
||||
{
|
||||
return Lambda.of(this, boundConstants, body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Selects the format used for pretty-printing expressions.
|
||||
* Remarks: The
|
||||
|
@ -2653,7 +2687,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Create a tactic that applies {@code t1} to a Goal and then
|
||||
* {@code t2"/> to every subgoal produced by <paramref name="t1}.
|
||||
* {@code t2} to every subgoal produced by {@code t1}
|
||||
**/
|
||||
public Tactic andThen(Tactic t1, Tactic t2, Tactic... ts)
|
||||
|
||||
|
@ -2734,7 +2768,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Create a tactic that applies {@code t1} to a given goal if the
|
||||
* probe {@code p"/> evaluates to true and <paramref name="t2}
|
||||
* probe {@code p} evaluates to true and {@code t2}
|
||||
* otherwise.
|
||||
**/
|
||||
public Tactic cond(Probe p, Tactic t1, Tactic t2)
|
||||
|
@ -2895,7 +2929,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is less than the value returned by {@code p2}
|
||||
**/
|
||||
public Probe lt(Probe p1, Probe p2)
|
||||
|
@ -2907,7 +2941,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is greater than the value returned by {@code p2}
|
||||
**/
|
||||
public Probe gt(Probe p1, Probe p2)
|
||||
|
@ -2919,7 +2953,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is less than or equal the value returned by
|
||||
* {@code p2}
|
||||
**/
|
||||
|
@ -2932,7 +2966,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is greater than or equal the value returned by
|
||||
* {@code p2}
|
||||
**/
|
||||
|
@ -2945,7 +2979,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is equal to the value returned by {@code p2}
|
||||
**/
|
||||
public Probe eq(Probe p1, Probe p2)
|
||||
|
@ -2957,7 +2991,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p1} and {@code p2} evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p1} and {@code p2} evaluate to {@code true}.
|
||||
**/
|
||||
public Probe and(Probe p1, Probe p2)
|
||||
{
|
||||
|
@ -2968,7 +3002,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p1} or {@code p2} evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p1} or {@code p2} evaluate to {@code true}.
|
||||
**/
|
||||
public Probe or(Probe p1, Probe p2)
|
||||
{
|
||||
|
@ -2979,7 +3013,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p} does not evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p} does not evaluate to {@code true}.
|
||||
**/
|
||||
public Probe not(Probe p)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ public class Quantifier extends BoolExpr
|
|||
**/
|
||||
public boolean isExistential()
|
||||
{
|
||||
return !isUniversal();
|
||||
return Native.isQuantifierExists(getContext().nCtx(), getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1766,6 +1766,34 @@ class QuantifierRef(BoolRef):
|
|||
"""
|
||||
return Z3_is_quantifier_forall(self.ctx_ref(), self.ast)
|
||||
|
||||
def is_exists(self):
|
||||
"""Return `True` if `self` is an existential quantifier.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort())
|
||||
>>> x = Int('x')
|
||||
>>> q = ForAll(x, f(x) == 0)
|
||||
>>> q.is_exists()
|
||||
False
|
||||
>>> q = Exists(x, f(x) != 0)
|
||||
>>> q.is_exists()
|
||||
True
|
||||
"""
|
||||
return Z3_is_quantifier_exists(self.ctx_ref(), self.ast)
|
||||
|
||||
def is_lambda(self):
|
||||
"""Return `True` if `self` is a lambda expression.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort())
|
||||
>>> x = Int('x')
|
||||
>>> q = Lambda(x, f(x))
|
||||
>>> q.is_lambda()
|
||||
True
|
||||
>>> q = Exists(x, f(x) != 0)
|
||||
>>> q.is_lambda()
|
||||
False
|
||||
"""
|
||||
return Z3_is_lambda(self.ctx_ref(), self.ast)
|
||||
|
||||
def weight(self):
|
||||
"""Return the weight annotation of `self`.
|
||||
|
||||
|
@ -1973,6 +2001,26 @@ def Exists(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
|
|||
"""
|
||||
return _mk_quantifier(False, vs, body, weight, qid, skid, patterns, no_patterns)
|
||||
|
||||
def Lambda(vs, body):
|
||||
"""Create a Z3 lambda expression.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort(), IntSort())
|
||||
>>> mem0 = Array('mem0', IntSort(), IntSort())
|
||||
>>> lo, hi, e, i = Ints('lo hi e i')
|
||||
>>> mem1 = Lambda([i], If(And(lo <= i, i <= hi), e, mem0[i]))
|
||||
>>> mem1
|
||||
Lambda(i, If(And(lo <= i, i <= hi), e, mem0[i]))
|
||||
"""
|
||||
ctx = body.ctx
|
||||
if is_app(vs):
|
||||
vs = [vs]
|
||||
num_vars = len(vs)
|
||||
_vs = (Ast * num_vars)()
|
||||
for i in range(num_vars):
|
||||
## TODO: Check if is constant
|
||||
_vs[i] = vs[i].as_ast()
|
||||
return QuantifierRef(Z3_mk_lambda_const(ctx.ref(), num_vars, _vs, body.as_ast()), ctx)
|
||||
|
||||
#########################################
|
||||
#
|
||||
# Arithmetic
|
||||
|
@ -5582,7 +5630,7 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e.num_args()
|
||||
2
|
||||
|
@ -5600,16 +5648,16 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
>>> e.num_args()
|
||||
2
|
||||
>>> e.arg_value(0)
|
||||
0
|
||||
>>> e.arg_value(1)
|
||||
1
|
||||
>>> e.arg_value(1)
|
||||
2
|
||||
>>> try:
|
||||
... e.arg_value(2)
|
||||
... except IndexError:
|
||||
|
@ -5631,14 +5679,14 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
>>> e.num_args()
|
||||
2
|
||||
>>> e.value()
|
||||
10
|
||||
20
|
||||
"""
|
||||
return _to_expr_ref(Z3_func_entry_get_value(self.ctx.ref(), self.entry), self.ctx)
|
||||
|
||||
|
@ -5652,10 +5700,10 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e.as_list()
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
"""
|
||||
args = [ self.arg_value(i) for i in range(self.num_args())]
|
||||
args.append(self.value())
|
||||
|
@ -5693,7 +5741,7 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].else_value()
|
||||
1
|
||||
"""
|
||||
|
@ -5713,9 +5761,9 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].num_entries()
|
||||
3
|
||||
1
|
||||
"""
|
||||
return int(Z3_func_interp_get_num_entries(self.ctx.ref(), self.f))
|
||||
|
||||
|
@ -5743,14 +5791,10 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].num_entries()
|
||||
3
|
||||
1
|
||||
>>> m[f].entry(0)
|
||||
[0, 1]
|
||||
>>> m[f].entry(1)
|
||||
[1, 1]
|
||||
>>> m[f].entry(2)
|
||||
[2, 0]
|
||||
"""
|
||||
if idx >= self.num_entries():
|
||||
|
@ -5777,9 +5821,9 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].as_list()
|
||||
[[0, 1], [1, 1], [2, 0], 1]
|
||||
[[2, 0], 1]
|
||||
"""
|
||||
r = [ self.entry(i).as_list() for i in range(self.num_entries())]
|
||||
r.append(self.else_value())
|
||||
|
@ -5891,7 +5935,7 @@ class ModelRef(Z3PPObject):
|
|||
>>> m[x]
|
||||
1
|
||||
>>> m[f]
|
||||
[1 -> 0, else -> 0]
|
||||
[else -> 0]
|
||||
"""
|
||||
if __debug__:
|
||||
_z3_assert(isinstance(decl, FuncDeclRef) or is_const(decl), "Z3 declaration expected")
|
||||
|
@ -6008,10 +6052,10 @@ class ModelRef(Z3PPObject):
|
|||
>>> m[x]
|
||||
1
|
||||
>>> m[f]
|
||||
[1 -> 0, else -> 0]
|
||||
[else -> 0]
|
||||
>>> for d in m: print("%s -> %s" % (d, m[d]))
|
||||
x -> 1
|
||||
f -> [1 -> 0, else -> 0]
|
||||
f -> [else -> 0]
|
||||
"""
|
||||
if _is_int(idx):
|
||||
if idx >= len(self):
|
||||
|
|
|
@ -959,8 +959,10 @@ class Formatter:
|
|||
ys_pp = seq3(ys, '[', ']')
|
||||
if a.is_forall():
|
||||
header = 'ForAll'
|
||||
else:
|
||||
elif a.is_exists():
|
||||
header = 'Exists'
|
||||
else:
|
||||
header = 'Lambda'
|
||||
return seq1(header, (ys_pp, body_pp))
|
||||
|
||||
def pp_expr(self, a, d, xs):
|
||||
|
|
|
@ -482,6 +482,10 @@ typedef enum
|
|||
T1: (~ p q)
|
||||
[quant-intro T1]: (~ (forall (x) p) (forall (x) q))
|
||||
|
||||
- Z3_OP_PR_BIND: Given a proof p, produces a proof of lambda x . p, where x are free variables in p.
|
||||
T1: f
|
||||
[proof-bind T1] forall (x) f
|
||||
|
||||
- Z3_OP_PR_DISTRIBUTIVITY: Distributivity proof object.
|
||||
Given that f (= or) distributes over g (= and), produces a proof for
|
||||
|
||||
|
@ -1109,6 +1113,7 @@ typedef enum {
|
|||
Z3_OP_PR_TRANSITIVITY_STAR,
|
||||
Z3_OP_PR_MONOTONICITY,
|
||||
Z3_OP_PR_QUANT_INTRO,
|
||||
Z3_OP_PR_BIND,
|
||||
Z3_OP_PR_DISTRIBUTIVITY,
|
||||
Z3_OP_PR_AND_ELIM,
|
||||
Z3_OP_PR_NOT_OR_ELIM,
|
||||
|
@ -1857,7 +1862,6 @@ extern "C" {
|
|||
*/
|
||||
Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const * domain, Z3_sort range);
|
||||
|
||||
|
||||
/**
|
||||
\brief Create a tuple type.
|
||||
|
||||
|
@ -2946,6 +2950,8 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief n-ary Array read.
|
||||
The argument \c a is the array and \c idxs are the indices of the array that gets read.
|
||||
|
@ -2955,6 +2961,7 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs);
|
||||
|
||||
|
||||
/**
|
||||
\brief Array update.
|
||||
|
||||
|
@ -2973,6 +2980,7 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v);
|
||||
|
||||
|
||||
/**
|
||||
\brief n-ary Array update.
|
||||
|
||||
|
@ -3763,6 +3771,54 @@ extern "C" {
|
|||
Z3_ast body
|
||||
);
|
||||
|
||||
/**
|
||||
\brief Create a lambda expression. It taks an expression \c body that contains bound variables
|
||||
of the same sorts as the sorts listed in the array \c sorts. The bound variables are de-Bruijn indices created
|
||||
using #Z3_mk_bound. The array \c decl_names contains the names that the quantified formula uses for the
|
||||
bound variables. Z3 applies the convention that the last element in the \c decl_names and \c sorts array
|
||||
refers to the variable with index 0, the second to last element of \c decl_names and \c sorts refers
|
||||
to the variable with index 1, etc.
|
||||
The sort of the resulting expression is \c (Array sorts range) where \c range is the sort of \c body.
|
||||
For example, if the lambda binds two variables of sort \c Int and \c Bool, and the \c body has sort \c Real,
|
||||
the sort of the expression is \c (Array Int Bool Real).
|
||||
|
||||
\param c logical context
|
||||
\param num_decls number of variables to be bound.
|
||||
\param sorts the sorts of the bound variables.
|
||||
\param decl_names names of the bound variables
|
||||
\param body the body of the lambda expression.
|
||||
|
||||
\sa Z3_mk_bound
|
||||
\sa Z3_mk_forall
|
||||
\sa Z3_mk_lambda_const
|
||||
|
||||
def_API('Z3_mk_lambda', AST, (_in(CONTEXT), _in(UINT), _in_array(1, SORT), _in_array(1, SYMBOL), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_lambda(Z3_context c,
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body);
|
||||
|
||||
/**
|
||||
\brief Create a lambda expression using a list of constants that form the set
|
||||
of bound variables
|
||||
|
||||
\param c logical context.
|
||||
\param num_bound number of constants to be abstracted into bound variables.
|
||||
\param bound array of constants to be abstracted into bound variables.
|
||||
\param body the body of the lambda expression.
|
||||
|
||||
\sa Z3_mk_bound
|
||||
\sa Z3_mk_forall
|
||||
\sa Z3_mk_lambda
|
||||
|
||||
def_API('Z3_mk_lambda_const', AST, (_in(CONTEXT), _in(UINT), _in_array(1, APP), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||
unsigned num_bound, Z3_app const bound[],
|
||||
Z3_ast body);
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Accessors */
|
||||
|
@ -4529,14 +4585,29 @@ extern "C" {
|
|||
unsigned Z3_API Z3_get_index_value(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if quantifier is universal.
|
||||
|
||||
\pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST
|
||||
\brief Determine if an ast is a universal quantifier.
|
||||
|
||||
def_API('Z3_is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_quantifier_forall(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if ast is an existential quantifier.
|
||||
|
||||
|
||||
def_API('Z3_is_quantifier_exists', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_quantifier_exists(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if ast is a lambda expresion.
|
||||
|
||||
\pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST
|
||||
|
||||
def_API('Z3_is_lambda', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_lambda(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Obtain weight of quantifier.
|
||||
|
||||
|
|
142
src/ast/ast.cpp
142
src/ast/ast.cpp
|
@ -26,6 +26,9 @@ Revision History:
|
|||
#include "util/string_buffer.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -360,13 +363,14 @@ app::app(func_decl * decl, unsigned num_args, expr * const * args):
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier::quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s,
|
||||
int weight, symbol const & qid, symbol const & skid, unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns):
|
||||
expr(AST_QUANTIFIER),
|
||||
m_forall(forall),
|
||||
m_kind(k),
|
||||
m_num_decls(num_decls),
|
||||
m_expr(body),
|
||||
m_sort(s),
|
||||
m_depth(::get_depth(body) + 1),
|
||||
m_weight(weight),
|
||||
m_has_unused_vars(true),
|
||||
|
@ -385,6 +389,25 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort
|
|||
memcpy(const_cast<expr **>(get_no_patterns()), no_patterns, sizeof(expr *) * num_no_patterns);
|
||||
}
|
||||
|
||||
quantifier::quantifier(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s):
|
||||
expr(AST_QUANTIFIER),
|
||||
m_kind(lambda_k),
|
||||
m_num_decls(num_decls),
|
||||
m_expr(body),
|
||||
m_sort(s),
|
||||
m_depth(::get_depth(body) + 1),
|
||||
m_weight(0),
|
||||
m_has_unused_vars(true),
|
||||
m_has_labels(::has_labels(body)),
|
||||
m_qid(symbol()),
|
||||
m_skid(symbol()),
|
||||
m_num_patterns(0),
|
||||
m_num_no_patterns(0) {
|
||||
memcpy(const_cast<sort **>(get_decl_sorts()), decl_sorts, sizeof(sort *) * num_decls);
|
||||
memcpy(const_cast<symbol*>(get_decl_names()), decl_names, sizeof(symbol) * num_decls);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Auxiliary functions
|
||||
|
@ -392,21 +415,16 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort
|
|||
// -----------------------------------
|
||||
|
||||
sort * get_sort(expr const * n) {
|
||||
while (true) {
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP:
|
||||
return to_app(n)->get_decl()->get_range();
|
||||
case AST_VAR:
|
||||
return to_var(n)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
// The sort of the quantifier is the sort of the nested expression.
|
||||
// This code assumes the given expression is well-sorted.
|
||||
n = to_quantifier(n)->get_expr();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP:
|
||||
return to_app(n)->get_decl()->get_range();
|
||||
case AST_VAR:
|
||||
return to_var(n)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
return to_quantifier(n)->get_sort();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +484,7 @@ bool compare_nodes(ast const * n1, ast const * n2) {
|
|||
to_var(n1)->get_sort() == to_var(n2)->get_sort();
|
||||
case AST_QUANTIFIER:
|
||||
return
|
||||
to_quantifier(n1)->is_forall() == to_quantifier(n2)->is_forall() &&
|
||||
to_quantifier(n1)->get_kind() == to_quantifier(n2)->get_kind() &&
|
||||
to_quantifier(n1)->get_num_decls() == to_quantifier(n2)->get_num_decls() &&
|
||||
compare_arrays(to_quantifier(n1)->get_decl_sorts(),
|
||||
to_quantifier(n2)->get_decl_sorts(),
|
||||
|
@ -566,7 +584,7 @@ unsigned get_node_hash(ast const * n) {
|
|||
case AST_QUANTIFIER:
|
||||
a = ast_array_hash(to_quantifier(n)->get_decl_sorts(),
|
||||
to_quantifier(n)->get_num_decls(),
|
||||
to_quantifier(n)->is_forall() ? 31 : 19);
|
||||
to_quantifier(n)->get_kind() == forall_k ? 31 : 19);
|
||||
b = to_quantifier(n)->get_num_patterns();
|
||||
c = to_quantifier(n)->get_expr()->hash();
|
||||
mix(a,b,c);
|
||||
|
@ -689,7 +707,8 @@ bool basic_decl_plugin::check_proof_sorts(basic_op_kind k, unsigned arity, sort
|
|||
for (unsigned i = 0; i < arity - 1; i++)
|
||||
if (domain[i] != m_proof_sort)
|
||||
return false;
|
||||
return domain[arity-1] == m_bool_sort || domain[arity-1] == m_proof_sort;
|
||||
#define is_array(_x_) true
|
||||
return domain[arity-1] == m_bool_sort || domain[arity-1] == m_proof_sort || is_array(domain[arity-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,7 +723,8 @@ bool basic_decl_plugin::check_proof_args(basic_op_kind k, unsigned num_args, exp
|
|||
return false;
|
||||
return
|
||||
m_manager->get_sort(args[num_args - 1]) == m_bool_sort ||
|
||||
m_manager->get_sort(args[num_args - 1]) == m_proof_sort;
|
||||
m_manager->get_sort(args[num_args - 1]) == m_proof_sort ||
|
||||
is_lambda(args[num_args-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,6 +838,7 @@ func_decl * basic_decl_plugin::mk_proof_decl(basic_op_kind k, unsigned num_paren
|
|||
case PR_TRANSITIVITY_STAR: return mk_proof_decl("trans*", k, num_parents, m_transitivity_star_decls);
|
||||
case PR_MONOTONICITY: return mk_proof_decl("monotonicity", k, num_parents, m_monotonicity_decls);
|
||||
case PR_QUANT_INTRO: return mk_proof_decl("quant-intro", k, 1, m_quant_intro_decl);
|
||||
case PR_BIND: UNREACHABLE();
|
||||
case PR_DISTRIBUTIVITY: return mk_proof_decl("distributivity", k, num_parents, m_distributivity_decls);
|
||||
case PR_AND_ELIM: return mk_proof_decl("and-elim", k, 1, m_and_elim_decl);
|
||||
case PR_NOT_OR_ELIM: return mk_proof_decl("not-or-elim", k, 1, m_not_or_elim_decl);
|
||||
|
@ -1054,6 +1075,10 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
// eq and oeq must have at least two arguments, they can have more since they are chainable
|
||||
case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, join(arity, domain), m_eq_decls) : nullptr;
|
||||
case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(arity, domain), m_oeq_decls) : nullptr;
|
||||
case PR_BIND: {
|
||||
func_decl_info info(m_family_id, PR_BIND);
|
||||
return m_manager->mk_func_decl(symbol("proof-bind"), arity, domain, m_proof_sort, info);
|
||||
}
|
||||
case OP_DISTINCT: {
|
||||
func_decl_info info(m_family_id, OP_DISTINCT);
|
||||
info.set_pairwise();
|
||||
|
@ -1097,6 +1122,11 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(num_args, args), m_oeq_decls) : nullptr;
|
||||
case OP_DISTINCT:
|
||||
return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range);
|
||||
case PR_BIND: {
|
||||
ptr_buffer<sort> sorts;
|
||||
for (unsigned i = 0; i < num_args; ++i) sorts.push_back(m_manager->get_sort(args[i]));
|
||||
return mk_func_decl(k, num_parameters, parameters, num_args, sorts.c_ptr(), range);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1218,7 +1248,6 @@ func_decl * model_value_decl_plugin::mk_func_decl(decl_kind k, unsigned num_para
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
SASSERT(k == OP_MODEL_VALUE);
|
||||
if (arity != 0 || num_parameters != 2 || !parameters[0].is_int() || !parameters[1].is_ast() || !is_sort(parameters[1].get_ast())) {
|
||||
UNREACHABLE();
|
||||
m_manager->raise_exception("invalid model value");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1290,7 +1319,8 @@ ast_manager::ast_manager(proof_gen_mode m, char const * trace_file, bool is_form
|
|||
m_proof_mode(m),
|
||||
m_trace_stream(nullptr),
|
||||
m_trace_stream_owner(false),
|
||||
m_rec_fun(":rec-fun") {
|
||||
m_rec_fun(":rec-fun"),
|
||||
m_lambda_def(":lambda-def") {
|
||||
|
||||
if (trace_file) {
|
||||
m_trace_stream = alloc(std::fstream, trace_file, std::ios_base::out);
|
||||
|
@ -1312,7 +1342,8 @@ ast_manager::ast_manager(proof_gen_mode m, std::fstream * trace_stream, bool is_
|
|||
m_proof_mode(m),
|
||||
m_trace_stream(trace_stream),
|
||||
m_trace_stream_owner(false),
|
||||
m_rec_fun(":rec-fun") {
|
||||
m_rec_fun(":rec-fun"),
|
||||
m_lambda_def(":lambda-def") {
|
||||
|
||||
if (!is_format_manager)
|
||||
m_format_manager = alloc(ast_manager, PGM_DISABLED, trace_stream, true);
|
||||
|
@ -1508,7 +1539,6 @@ void ast_manager::raise_exception(char const * msg) {
|
|||
throw ast_exception(msg);
|
||||
}
|
||||
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
void ast_manager::copy_families_plugins(ast_manager const & from) {
|
||||
TRACE("copy_families_plugins",
|
||||
|
@ -1761,6 +1791,7 @@ ast * ast_manager::register_node_core(ast * n) {
|
|||
case AST_QUANTIFIER:
|
||||
inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
|
||||
inc_ref(to_quantifier(n)->get_expr());
|
||||
inc_ref(to_quantifier(n)->get_sort());
|
||||
inc_array_ref(to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
|
||||
inc_array_ref(to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
|
||||
break;
|
||||
|
@ -1824,6 +1855,7 @@ void ast_manager::delete_node(ast * n) {
|
|||
case AST_QUANTIFIER:
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts());
|
||||
dec_ref(worklist, to_quantifier(n)->get_expr());
|
||||
dec_ref(worklist, to_quantifier(n)->get_sort());
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns());
|
||||
dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns());
|
||||
break;
|
||||
|
@ -2338,7 +2370,7 @@ bool ast_manager::is_pattern(expr const * n, ptr_vector<expr> &args) {
|
|||
}
|
||||
|
||||
|
||||
quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names,
|
||||
quantifier * ast_manager::mk_quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names,
|
||||
expr * body, int weight , symbol const & qid, symbol const & skid,
|
||||
unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns) {
|
||||
|
@ -2353,7 +2385,17 @@ quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort *
|
|||
}});
|
||||
unsigned sz = quantifier::get_obj_size(num_decls, num_patterns, num_no_patterns);
|
||||
void * mem = allocate_node(sz);
|
||||
quantifier * new_node = new (mem) quantifier(forall, num_decls, decl_sorts, decl_names, body,
|
||||
|
||||
sort* s = nullptr;
|
||||
if (k == lambda_k) {
|
||||
array_util autil(*this);
|
||||
s = autil.mk_array_sort(num_decls, decl_sorts, ::get_sort(body));
|
||||
}
|
||||
else {
|
||||
s = mk_bool_sort();
|
||||
}
|
||||
|
||||
quantifier * new_node = new (mem) quantifier(k, num_decls, decl_sorts, decl_names, body, s,
|
||||
weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
quantifier * r = register_node(new_node);
|
||||
|
@ -2370,6 +2412,18 @@ quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort *
|
|||
return r;
|
||||
}
|
||||
|
||||
quantifier * ast_manager::mk_lambda(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body) {
|
||||
SASSERT(body);
|
||||
unsigned sz = quantifier::get_obj_size(num_decls, 0, 0);
|
||||
void * mem = allocate_node(sz);
|
||||
array_util autil(*this);
|
||||
sort* s = autil.mk_array_sort(num_decls, decl_sorts, ::get_sort(body));
|
||||
quantifier * new_node = new (mem) quantifier(num_decls, decl_sorts, decl_names, body, s);
|
||||
quantifier * r = register_node(new_node);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// Return true if the patterns of q are the given ones.
|
||||
static bool same_patterns(quantifier * q, unsigned num_patterns, expr * const * patterns) {
|
||||
if (num_patterns != q->get_num_patterns())
|
||||
|
@ -2393,7 +2447,7 @@ static bool same_no_patterns(quantifier * q, unsigned num_no_patterns, expr * co
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && same_patterns(q, num_patterns, patterns))
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2410,7 +2464,7 @@ quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_pattern
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_patterns, expr * const * patterns, unsigned num_no_patterns, expr * const * no_patterns, expr * body) {
|
||||
if (q->get_expr() == body && same_patterns(q, num_patterns, patterns) && same_no_patterns(q, num_no_patterns, no_patterns))
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2427,7 +2481,7 @@ quantifier * ast_manager::update_quantifier(quantifier * q, unsigned num_pattern
|
|||
quantifier * ast_manager::update_quantifier(quantifier * q, expr * body) {
|
||||
if (q->get_expr() == body)
|
||||
return q;
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2445,7 +2499,7 @@ quantifier * ast_manager::update_quantifier_weight(quantifier * q, int w) {
|
|||
if (q->get_weight() == w)
|
||||
return q;
|
||||
TRACE("update_quantifier_weight", tout << "#" << q->get_id() << " " << q->get_weight() << " -> " << w << "\n";);
|
||||
return mk_quantifier(q->is_forall(),
|
||||
return mk_quantifier(q->get_kind(),
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2459,10 +2513,10 @@ quantifier * ast_manager::update_quantifier_weight(quantifier * q, int w) {
|
|||
q->get_no_patterns());
|
||||
}
|
||||
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, expr * body) {
|
||||
if (q->get_expr() == body && q->is_forall() == is_forall)
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, quantifier_kind k, expr * body) {
|
||||
if (q->get_expr() == body && q->get_kind() == k)
|
||||
return q;
|
||||
return mk_quantifier(is_forall,
|
||||
return mk_quantifier(k,
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2476,10 +2530,10 @@ quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, expr
|
|||
q->get_no_patterns());
|
||||
}
|
||||
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && q->is_forall() == is_forall && same_patterns(q, num_patterns, patterns))
|
||||
quantifier * ast_manager::update_quantifier(quantifier * q, quantifier_kind k, unsigned num_patterns, expr * const * patterns, expr * body) {
|
||||
if (q->get_expr() == body && q->get_kind() == k && same_patterns(q, num_patterns, patterns))
|
||||
return q;
|
||||
return mk_quantifier(is_forall,
|
||||
return mk_quantifier(k,
|
||||
q->get_num_decls(),
|
||||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
|
@ -2786,11 +2840,17 @@ proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs,
|
|||
return mk_monotonicity(mk_func_decl(m_basic_family_id, OP_OEQ, 0, nullptr, 2, d), f1, f2, num_proofs, proofs);
|
||||
}
|
||||
|
||||
|
||||
proof * ast_manager::mk_bind_proof(quantifier * q, proof * p) {
|
||||
expr* b = mk_lambda(q->get_num_decls(), q->get_decl_sorts(), q->get_decl_names(), p);
|
||||
return mk_app(m_basic_family_id, PR_BIND, b);
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_eq(get_fact(p)));
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_eq(get_fact(p)) || is_lambda(get_fact(p)));
|
||||
return mk_app(m_basic_family_id, PR_QUANT_INTRO, p, mk_iff(q1, q2));
|
||||
}
|
||||
|
||||
|
|
|
@ -793,11 +793,18 @@ public:
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
enum quantifier_kind {
|
||||
forall_k,
|
||||
exists_k,
|
||||
lambda_k
|
||||
};
|
||||
|
||||
class quantifier : public expr {
|
||||
friend class ast_manager;
|
||||
bool m_forall;
|
||||
quantifier_kind m_kind;
|
||||
unsigned m_num_decls;
|
||||
expr * m_expr;
|
||||
sort * m_sort;
|
||||
unsigned m_depth;
|
||||
// extra fields
|
||||
int m_weight;
|
||||
|
@ -813,12 +820,18 @@ class quantifier : public expr {
|
|||
return sizeof(quantifier) + num_decls * (sizeof(sort *) + sizeof(symbol)) + (num_patterns + num_no_patterns) * sizeof(expr*);
|
||||
}
|
||||
|
||||
quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* s,
|
||||
int weight, symbol const & qid, symbol const & skid, unsigned num_patterns, expr * const * patterns,
|
||||
unsigned num_no_patterns, expr * const * no_patterns);
|
||||
|
||||
quantifier(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body, sort* sort);
|
||||
|
||||
public:
|
||||
bool is_forall() const { return m_forall; }
|
||||
bool is_exists() const { return !m_forall; }
|
||||
quantifier_kind get_kind() const { return m_kind; }
|
||||
// bool is_forall() const { return m_kind == forall_k; }
|
||||
// bool is_exists() const { return m_kind == exists_k; }
|
||||
// bool is_lambda() const { return m_kind == lambda_k; }
|
||||
|
||||
unsigned get_num_decls() const { return m_num_decls; }
|
||||
sort * const * get_decl_sorts() const { return reinterpret_cast<sort * const *>(m_patterns_decls); }
|
||||
symbol const * get_decl_names() const { return reinterpret_cast<symbol const *>(get_decl_sorts() + m_num_decls); }
|
||||
|
@ -826,6 +839,8 @@ public:
|
|||
symbol const & get_decl_name(unsigned idx) const { return get_decl_names()[idx]; }
|
||||
expr * get_expr() const { return m_expr; }
|
||||
|
||||
sort * get_sort() const { return m_sort; }
|
||||
|
||||
unsigned get_depth() const { return m_depth; }
|
||||
|
||||
int get_weight() const { return m_weight; }
|
||||
|
@ -844,6 +859,7 @@ public:
|
|||
void set_no_unused_vars() { m_has_unused_vars = false; }
|
||||
|
||||
bool has_labels() const { return m_has_labels; }
|
||||
|
||||
|
||||
unsigned get_num_children() const { return 1 + get_num_patterns() + get_num_no_patterns(); }
|
||||
expr * get_child(unsigned idx) const {
|
||||
|
@ -871,8 +887,9 @@ inline bool is_app(ast const * n) { return n->get_kind() == AST_APP; }
|
|||
inline bool is_var(ast const * n) { return n->get_kind() == AST_VAR; }
|
||||
inline bool is_var(ast const * n, unsigned& idx) { return is_var(n) && (idx = static_cast<var const*>(n)->get_idx(), true); }
|
||||
inline bool is_quantifier(ast const * n) { return n->get_kind() == AST_QUANTIFIER; }
|
||||
inline bool is_forall(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->is_forall(); }
|
||||
inline bool is_exists(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->is_exists(); }
|
||||
inline bool is_forall(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == forall_k; }
|
||||
inline bool is_exists(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == exists_k; }
|
||||
inline bool is_lambda(ast const * n) { return is_quantifier(n) && static_cast<quantifier const *>(n)->get_kind() == lambda_k; }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -950,7 +967,7 @@ protected:
|
|||
family_id m_family_id;
|
||||
|
||||
virtual void set_manager(ast_manager * m, family_id id) {
|
||||
SASSERT(m_manager == 0);
|
||||
SASSERT(m_manager == nullptr);
|
||||
m_manager = m;
|
||||
m_family_id = id;
|
||||
}
|
||||
|
@ -1043,7 +1060,7 @@ enum basic_sort_kind {
|
|||
enum basic_op_kind {
|
||||
OP_TRUE, OP_FALSE, OP_EQ, OP_DISTINCT, OP_ITE, OP_AND, OP_OR, OP_XOR, OP_NOT, OP_IMPLIES, OP_OEQ, LAST_BASIC_OP,
|
||||
|
||||
PR_UNDEF, PR_TRUE, PR_ASSERTED, PR_GOAL, PR_MODUS_PONENS, PR_REFLEXIVITY, PR_SYMMETRY, PR_TRANSITIVITY, PR_TRANSITIVITY_STAR, PR_MONOTONICITY, PR_QUANT_INTRO,
|
||||
PR_UNDEF, PR_TRUE, PR_ASSERTED, PR_GOAL, PR_MODUS_PONENS, PR_REFLEXIVITY, PR_SYMMETRY, PR_TRANSITIVITY, PR_TRANSITIVITY_STAR, PR_MONOTONICITY, PR_QUANT_INTRO, PR_BIND,
|
||||
PR_DISTRIBUTIVITY, PR_AND_ELIM, PR_NOT_OR_ELIM, PR_REWRITE, PR_REWRITE_STAR, PR_PULL_QUANT,
|
||||
PR_PUSH_QUANT, PR_ELIM_UNUSED_VARS, PR_DER, PR_QUANT_INST,
|
||||
|
||||
|
@ -1487,6 +1504,7 @@ protected:
|
|||
#endif
|
||||
ast_manager * m_format_manager; // hack for isolating format objects in a different manager.
|
||||
symbol m_rec_fun;
|
||||
symbol m_lambda_def;
|
||||
|
||||
void init();
|
||||
|
||||
|
@ -1594,9 +1612,12 @@ public:
|
|||
bool contains(ast * a) const { return m_ast_table.contains(a); }
|
||||
|
||||
bool is_rec_fun_def(quantifier* q) const { return q->get_qid() == m_rec_fun; }
|
||||
bool is_lambda_def(quantifier* q) const { return q->get_qid() == m_lambda_def; }
|
||||
|
||||
symbol const& rec_fun_qid() const { return m_rec_fun; }
|
||||
|
||||
symbol const& lambda_def_qid() const { return m_lambda_def; }
|
||||
|
||||
unsigned get_num_asts() const { return m_ast_table.size(); }
|
||||
|
||||
void debug_ref_count() { m_debug_ref_count = true; }
|
||||
|
@ -1892,7 +1913,7 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
quantifier * mk_quantifier(bool forall, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
quantifier * mk_quantifier(quantifier_kind k, unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body,
|
||||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr);
|
||||
|
@ -1901,7 +1922,7 @@ public:
|
|||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr) {
|
||||
return mk_quantifier(true, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
return mk_quantifier(forall_k, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
}
|
||||
|
||||
|
@ -1909,10 +1930,12 @@ public:
|
|||
int weight = 0, symbol const & qid = symbol::null, symbol const & skid = symbol::null,
|
||||
unsigned num_patterns = 0, expr * const * patterns = nullptr,
|
||||
unsigned num_no_patterns = 0, expr * const * no_patterns = nullptr) {
|
||||
return mk_quantifier(false, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
return mk_quantifier(exists_k, num_decls, decl_sorts, decl_names, body, weight, qid, skid, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns);
|
||||
}
|
||||
|
||||
quantifier * mk_lambda(unsigned num_decls, sort * const * decl_sorts, symbol const * decl_names, expr * body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, unsigned new_num_patterns, expr * const * new_patterns, unsigned new_num_no_patterns, expr * const * new_no_patterns, expr * new_body);
|
||||
|
@ -1921,9 +1944,9 @@ public:
|
|||
|
||||
quantifier * update_quantifier_weight(quantifier * q, int new_weight);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, bool new_is_forall, expr * new_body);
|
||||
quantifier * update_quantifier(quantifier * q, quantifier_kind new_kind, expr * new_body);
|
||||
|
||||
quantifier * update_quantifier(quantifier * q, bool new_is_forall, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
quantifier * update_quantifier(quantifier * q, quantifier_kind new_kind, unsigned new_num_patterns, expr * const * new_patterns, expr * new_body);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -2213,6 +2236,7 @@ public:
|
|||
proof * mk_rewrite(expr * s, expr * t);
|
||||
proof * mk_oeq_rewrite(expr * s, expr * t);
|
||||
proof * mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs);
|
||||
proof * mk_bind_proof(quantifier * q, proof * p);
|
||||
proof * mk_pull_quant(expr * e, quantifier * q);
|
||||
proof * mk_push_quant(quantifier * q, expr * e);
|
||||
proof * mk_elim_unused_vars(quantifier * q, expr * r);
|
||||
|
|
|
@ -242,7 +242,7 @@ public:
|
|||
|
||||
void operator()(quantifier * n) {
|
||||
display_def_header(n);
|
||||
m_out << "(" << (n->is_forall() ? "forall" : "exists") << " ";
|
||||
m_out << "(" << (n->get_kind() == forall_k ? "forall" : (n->get_kind() == exists_k ? "exists" : "lambda")) << " ";
|
||||
unsigned num_decls = n->get_num_decls();
|
||||
m_out << "(vars ";
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
|
|
|
@ -102,7 +102,7 @@ bool lt(ast * n1, ast * n2) {
|
|||
UNREACHABLE();
|
||||
return false;
|
||||
case AST_QUANTIFIER:
|
||||
check_bool(to_quantifier(n1)->is_forall(), to_quantifier(n2)->is_forall());
|
||||
check_value(to_quantifier(n1)->get_kind(), to_quantifier(n2)->get_kind());
|
||||
check_value(to_quantifier(n1)->get_num_decls(), to_quantifier(n2)->get_num_decls());
|
||||
check_value(to_quantifier(n1)->get_num_patterns(), to_quantifier(n2)->get_num_patterns());
|
||||
check_value(to_quantifier(n1)->get_num_no_patterns(), to_quantifier(n2)->get_num_no_patterns());
|
||||
|
|
|
@ -994,7 +994,7 @@ class smt2_printer {
|
|||
}
|
||||
format * f_decls = pp_var_decls(q);
|
||||
format * fs[2] = { f_decls, f_body };
|
||||
char const * header = q->is_forall() ? "forall" : "exists";
|
||||
char const * header = q->get_kind() == forall_k ? "forall" : (q->get_kind() == exists_k ? "exists" : "lambda");
|
||||
format * f = mk_seq3<format**, f2f>(m(), fs, fs+2, f2f(), header, 1, SMALL_INDENT);
|
||||
|
||||
info f_info = m_info_stack.back();
|
||||
|
|
|
@ -495,11 +495,10 @@ class smt_printer {
|
|||
m_qlists.push_back(q);
|
||||
|
||||
m_out << "(";
|
||||
if (q->is_forall()) {
|
||||
m_out << "forall ";
|
||||
}
|
||||
else {
|
||||
m_out << "exists ";
|
||||
switch (q->get_kind()) {
|
||||
case forall_k: m_out << "forall "; break;
|
||||
case exists_k: m_out << "exists "; break;
|
||||
case lambda_k: m_out << "lambda "; break;
|
||||
}
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
|
|
|
@ -279,7 +279,7 @@ ast * ast_translation::process(ast const * _n) {
|
|||
expr ** pats = reinterpret_cast<expr**>(m_result_stack.c_ptr() + fr.m_rpos + num_decls + 1);
|
||||
unsigned num_no_pats = to_quantifier(n)->get_num_no_patterns();
|
||||
expr ** no_pats = pats + num_pats;
|
||||
quantifier * new_q = m_to_manager.mk_quantifier(to_quantifier(n)->is_forall(),
|
||||
quantifier * new_q = m_to_manager.mk_quantifier(to_quantifier(n)->get_kind(),
|
||||
num_decls,
|
||||
dsorts,
|
||||
dnames,
|
||||
|
|
|
@ -115,7 +115,7 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
|
|||
tout << result << "\n";);
|
||||
}
|
||||
|
||||
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
expr_ref mk_quantifier(quantifier_kind k, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
expr_ref result(m);
|
||||
expr_abstract(m, 0, num_bound, (expr* const*)bound, n, result);
|
||||
if (num_bound > 0) {
|
||||
|
@ -125,7 +125,7 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
|
|||
sorts.push_back(m.get_sort(bound[i]));
|
||||
names.push_back(bound[i]->get_decl()->get_name());
|
||||
}
|
||||
result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
result = m.mk_quantifier(k, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
}
|
||||
TRACE("expr_abstract",
|
||||
tout << expr_ref(n, m) << "\n";
|
||||
|
@ -137,9 +137,9 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
|
|||
}
|
||||
|
||||
expr_ref mk_forall(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(true, m, num_bound, bound, n);
|
||||
return mk_quantifier(forall_k, m, num_bound, bound, n);
|
||||
}
|
||||
|
||||
expr_ref mk_exists(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(false, m, num_bound, bound, n);
|
||||
return mk_quantifier(exists_k, m, num_bound, bound, n);
|
||||
}
|
||||
|
|
|
@ -194,6 +194,9 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(old_q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = old_q->get_num_decls();
|
||||
|
@ -217,7 +220,7 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
result = m().mk_quantifier(old_q->get_kind(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = nullptr;
|
||||
|
|
|
@ -23,7 +23,7 @@ Revision History:
|
|||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
TRACE("macro_finder", tout << "processing: " << mk_pp(n, m) << "\n";);
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
|
@ -46,7 +46,7 @@ bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
|||
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
|
||||
*/
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
@ -117,7 +117,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, e
|
|||
}
|
||||
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
|
|
@ -283,13 +283,11 @@ struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
|||
subst_args[nidx] = n->get_arg(i);
|
||||
}
|
||||
var_subst s(m);
|
||||
expr_ref rr(m);
|
||||
s(def, num, subst_args.c_ptr(), rr);
|
||||
expr_ref rr = s(def, num, subst_args.c_ptr());
|
||||
m_trail.push_back(rr);
|
||||
r = rr;
|
||||
if (m.proofs_enabled()) {
|
||||
expr_ref instance(m);
|
||||
s(q->get_expr(), num, subst_args.c_ptr(), instance);
|
||||
expr_ref instance = s(q->get_expr(), num, subst_args.c_ptr());
|
||||
proof * qi_pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), instance), num, subst_args.c_ptr());
|
||||
proof * q_pr = nullptr;
|
||||
mm.m_decl2macro_pr.find(d, q_pr);
|
||||
|
|
|
@ -334,7 +334,7 @@ bool macro_util::is_pseudo_head(expr * n, unsigned num_decls, app_ref & head, ap
|
|||
where t is a ground term, (f X) is the head.
|
||||
*/
|
||||
bool macro_util::is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
if (!is_forall(n))
|
||||
return false;
|
||||
TRACE("macro_util", tout << "processing: " << mk_pp(n, m_manager) << "\n";);
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
|
@ -485,7 +485,7 @@ void macro_util::normalize_expr(app * head, unsigned num_decls, expr * t, expr_r
|
|||
if (var_mapping[i] != 0)
|
||||
tout << "#" << i << " -> " << mk_ll_pp(var_mapping[i], m_manager);
|
||||
});
|
||||
subst(t, var_mapping.size(), var_mapping.c_ptr(), norm_t);
|
||||
norm_t = subst(t, var_mapping.size(), var_mapping.c_ptr());
|
||||
}
|
||||
else {
|
||||
norm_t = t;
|
||||
|
|
|
@ -155,7 +155,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
||||
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
||||
|
||||
if (is_quantifier(e) && to_quantifier(e)->is_forall()) {
|
||||
if (is_forall(e)) {
|
||||
quantifier * q = to_quantifier(e);
|
||||
expr * qe = q->get_expr();
|
||||
if ((m_manager.is_eq(qe))) {
|
||||
|
@ -251,7 +251,7 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
|||
|
||||
eq = m_manager.mk_eq(appl, ite);
|
||||
|
||||
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
||||
macro = m_manager.mk_quantifier(forall_k, new_var_names_rev.size(),
|
||||
new_qsorts_rev.c_ptr(), new_var_names_rev.c_ptr(), eq);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,17 +16,19 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
|
||||
struct defined_names::impl {
|
||||
typedef obj_map<expr, app *> expr2name;
|
||||
typedef obj_map<expr, proof *> expr2proof;
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
symbol m_z3name;
|
||||
|
||||
/**
|
||||
|
@ -60,9 +62,9 @@ struct defined_names::impl {
|
|||
app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer<symbol> & var_names);
|
||||
void cache_new_name(expr * e, app * name);
|
||||
void cache_new_name_intro_proof(expr * e, proof * pr);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result);
|
||||
virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result, symbol const& qid = symbol::null);
|
||||
void bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result, symbol const& qid = symbol::null);
|
||||
virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def);
|
||||
bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
|
||||
void push_scope();
|
||||
void pop_scope(unsigned num_scopes);
|
||||
|
@ -74,12 +76,13 @@ struct defined_names::impl {
|
|||
|
||||
struct defined_names::pos_impl : public defined_names::impl {
|
||||
pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {}
|
||||
void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) override;
|
||||
void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
defined_names::impl::impl(ast_manager & m, char const * prefix):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_exprs(m),
|
||||
m_names(m),
|
||||
m_apply_proofs(m) {
|
||||
|
@ -107,20 +110,20 @@ app * defined_names::impl::gen_name(expr * e, sort_ref_buffer & var_sorts, buffe
|
|||
sort * s = uv.get(i);
|
||||
if (s) {
|
||||
domain.push_back(s);
|
||||
new_args.push_back(m_manager.mk_var(i, s));
|
||||
new_args.push_back(m.mk_var(i, s));
|
||||
var_sorts.push_back(s);
|
||||
}
|
||||
else {
|
||||
var_sorts.push_back(m_manager.mk_bool_sort()); // could be any sort.
|
||||
var_sorts.push_back(m.mk_bool_sort()); // could be any sort.
|
||||
}
|
||||
var_names.push_back(symbol(i));
|
||||
}
|
||||
|
||||
sort * range = m_manager.get_sort(e);
|
||||
func_decl * new_skolem_decl = m_manager.mk_fresh_func_decl(m_z3name, symbol::null, domain.size(), domain.c_ptr(), range);
|
||||
app * n = m_manager.mk_app(new_skolem_decl, new_args.size(), new_args.c_ptr());
|
||||
TRACE("mk_definition_bug", tout << "gen_name: " << mk_ismt2_pp(n, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < var_sorts.size(); i++) tout << mk_pp(var_sorts[i], m_manager) << " ";
|
||||
sort * range = m.get_sort(e);
|
||||
func_decl * new_skolem_decl = m.mk_fresh_func_decl(m_z3name, symbol::null, domain.size(), domain.c_ptr(), range);
|
||||
app * n = m.mk_app(new_skolem_decl, new_args.size(), new_args.c_ptr());
|
||||
TRACE("mk_definition_bug", tout << "gen_name: " << mk_ismt2_pp(n, m) << "\n";
|
||||
for (unsigned i = 0; i < var_sorts.size(); i++) tout << mk_pp(var_sorts[i], m) << " ";
|
||||
tout << "\n";);
|
||||
return n;
|
||||
}
|
||||
|
@ -148,22 +151,22 @@ void defined_names::impl::cache_new_name_intro_proof(expr * e, proof * pr) {
|
|||
A quantifier is added around \c def_conjunct, if sorts and names are not empty.
|
||||
In this case, The application \c name is used as a pattern for the new quantifier.
|
||||
*/
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result) {
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref & result, symbol const& qid) {
|
||||
SASSERT(sorts.size() == names.size());
|
||||
if (sorts.empty())
|
||||
result = def_conjunct;
|
||||
else {
|
||||
expr * patterns[1] = { m_manager.mk_pattern(name) };
|
||||
quantifier_ref q(m_manager);
|
||||
q = m_manager.mk_forall(sorts.size(),
|
||||
expr * patterns[1] = { m.mk_pattern(name) };
|
||||
quantifier_ref q(m);
|
||||
q = m.mk_forall(sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
def_conjunct,
|
||||
1, symbol::null, symbol::null,
|
||||
1, qid, symbol::null,
|
||||
1, patterns);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";);
|
||||
elim_unused_vars(m_manager, q, params_ref(), result);
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m) << "\n";);
|
||||
result = elim_unused_vars(m, q, params_ref());
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,44 +175,81 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
|
|||
A quantifier is added around \c def_conjunct, if sorts and names are not empty.
|
||||
In this case, The application \c name is used as a pattern for the new quantifier.
|
||||
*/
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result) {
|
||||
expr_ref tmp(m_manager);
|
||||
bound_vars(sorts, names, def_conjunct, name, tmp);
|
||||
void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbol> const & names, expr * def_conjunct, app * name, expr_ref_buffer & result, symbol const& qid) {
|
||||
expr_ref tmp(m);
|
||||
bound_vars(sorts, names, def_conjunct, name, tmp, qid);
|
||||
result.push_back(tmp);
|
||||
}
|
||||
|
||||
#define MK_OR m_manager.mk_or
|
||||
#define MK_NOT m_manager.mk_not
|
||||
#define MK_EQ m_manager.mk_eq
|
||||
#define MK_OR m.mk_or
|
||||
#define MK_NOT m.mk_not
|
||||
#define MK_EQ m.mk_eq
|
||||
|
||||
void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) {
|
||||
expr_ref_buffer defs(m_manager);
|
||||
if (m_manager.is_bool(e)) {
|
||||
void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) {
|
||||
expr_ref_buffer defs(m);
|
||||
if (m.is_bool(e)) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(n), e), n, defs);
|
||||
bound_vars(var_sorts, var_names, MK_OR(n, MK_NOT(e)), n, defs);
|
||||
}
|
||||
else if (m_manager.is_term_ite(e)) {
|
||||
else if (m.is_term_ite(e)) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(to_app(e)->get_arg(0)), MK_EQ(n, to_app(e)->get_arg(1))), n, defs);
|
||||
bound_vars(var_sorts, var_names, MK_OR(to_app(e)->get_arg(0), MK_EQ(n, to_app(e)->get_arg(2))), n, defs);
|
||||
}
|
||||
else if (is_lambda(e)) {
|
||||
// n(y) = \x . M[x,y]
|
||||
// =>
|
||||
// n(y)[x] = M, forall x y
|
||||
//
|
||||
// NB. The pattern is incomplete.
|
||||
// consider store(a, i, v) == \lambda j . if i = j then v else a[j]
|
||||
// the instantiation rules for store(a, i, v) are:
|
||||
// sotre(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
|
||||
// The first pattern is not included.
|
||||
// TBD use a model-based scheme for exracting instantiations instead of
|
||||
// using multi-patterns.
|
||||
//
|
||||
|
||||
quantifier* q = to_quantifier(e);
|
||||
expr_ref_vector args(m);
|
||||
expr_ref n2(m), n3(m);
|
||||
var_shifter vs(m);
|
||||
vs(n, q->get_num_decls(), n2);
|
||||
args.push_back(n2);
|
||||
var_sorts.append(q->get_num_decls(), q->get_decl_sorts());
|
||||
var_names.append(q->get_num_decls(), q->get_decl_names());
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
args.push_back(m.mk_var(q->get_num_decls() - i - 1, q->get_decl_sort(i)));
|
||||
}
|
||||
array_util autil(m);
|
||||
func_decl * f = 0;
|
||||
if (autil.is_as_array(n2, f)) {
|
||||
n3 = m.mk_app(f, args.size()-1, args.c_ptr() + 1);
|
||||
}
|
||||
else {
|
||||
n3 = autil.mk_select(args.size(), args.c_ptr());
|
||||
}
|
||||
bound_vars(var_sorts, var_names, MK_EQ(q->get_expr(), n3), to_app(n3), defs, m.lambda_def_qid());
|
||||
|
||||
}
|
||||
else {
|
||||
bound_vars(var_sorts, var_names, MK_EQ(e, n), n, defs);
|
||||
}
|
||||
new_def = defs.size() == 1 ? defs[0] : m_manager.mk_and(defs.size(), defs.c_ptr());
|
||||
new_def = mk_and(m, defs.size(), defs.c_ptr());
|
||||
}
|
||||
|
||||
void defined_names::pos_impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> const & var_names, expr_ref & new_def) {
|
||||
|
||||
void defined_names::pos_impl::mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer<symbol> & var_names, expr_ref & new_def) {
|
||||
bound_vars(var_sorts, var_names, MK_OR(MK_NOT(n), e), n, new_def);
|
||||
}
|
||||
|
||||
bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
|
||||
TRACE("mk_definition_bug", tout << "making name for:\n" << mk_ismt2_pp(e, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "making name for:\n" << mk_ismt2_pp(e, m) << "\n";);
|
||||
|
||||
app * n_ptr;
|
||||
if (m_expr2name.find(e, n_ptr)) {
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
n = n_ptr;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
if (m.proofs_enabled()) {
|
||||
proof * pr_ptr = nullptr;
|
||||
m_expr2proof.find(e, pr_ptr);
|
||||
SASSERT(pr_ptr);
|
||||
|
@ -218,24 +258,24 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
sort_ref_buffer var_sorts(m_manager);
|
||||
sort_ref_buffer var_sorts(m);
|
||||
buffer<symbol> var_names;
|
||||
|
||||
n = gen_name(e, var_sorts, var_names);
|
||||
cache_new_name(e, n);
|
||||
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m) << "\n";);
|
||||
// variables are in reverse order in quantifiers
|
||||
std::reverse(var_sorts.c_ptr(), var_sorts.c_ptr() + var_sorts.size());
|
||||
std::reverse(var_names.c_ptr(), var_names.c_ptr() + var_names.size());
|
||||
|
||||
mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m_manager) << "\n";);
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m) << "\n";);
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
new_def_pr = m_manager.mk_def_intro(new_def);
|
||||
pr = m_manager.mk_apply_def(e, n, new_def_pr);
|
||||
if (m.proofs_enabled()) {
|
||||
new_def_pr = m.mk_def_intro(new_def);
|
||||
pr = m.mk_apply_def(e, n, new_def_pr);
|
||||
cache_new_name_intro_proof(e, pr);
|
||||
}
|
||||
return true;
|
||||
|
@ -257,7 +297,7 @@ void defined_names::impl::pop_scope(unsigned num_scopes) {
|
|||
SASSERT(sz == m_names.size());
|
||||
while (old_sz != sz) {
|
||||
--sz;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
if (m.proofs_enabled()) {
|
||||
m_expr2proof.erase(m_exprs.back());
|
||||
m_apply_proofs.pop_back();
|
||||
}
|
||||
|
@ -296,6 +336,15 @@ bool defined_names::mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_de
|
|||
return m_pos_impl->mk_name(e, new_def, new_def_pr, n, pr);
|
||||
}
|
||||
|
||||
expr_ref defined_names::mk_definition(expr * e, app * n) {
|
||||
ast_manager& m = m_impl->m;
|
||||
sort_ref_buffer var_sorts(m);
|
||||
expr_ref new_def(m);
|
||||
buffer<symbol> var_names;
|
||||
m_impl->mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
return new_def;
|
||||
}
|
||||
|
||||
void defined_names::push() {
|
||||
m_impl->push_scope();
|
||||
m_pos_impl->push_scope();
|
||||
|
|
|
@ -77,6 +77,11 @@ public:
|
|||
*/
|
||||
bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
|
||||
|
||||
/**
|
||||
\brief Create a definition for 'n' using 'e'.
|
||||
*/
|
||||
expr_ref mk_definition(expr * e, app * n);
|
||||
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
void reset();
|
||||
|
|
|
@ -22,7 +22,7 @@ Notes:
|
|||
|
||||
class name_exprs_core : public name_exprs {
|
||||
struct cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
defined_names & m_defined_names;
|
||||
expr_predicate & m_pred;
|
||||
|
||||
|
@ -33,7 +33,7 @@ class name_exprs_core : public name_exprs {
|
|||
proof_ref_vector * m_def_proofs;
|
||||
|
||||
cfg(ast_manager & m, defined_names & n, expr_predicate & pred):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_defined_names(n),
|
||||
m_pred(pred),
|
||||
m_r(m),
|
||||
|
@ -43,12 +43,12 @@ class name_exprs_core : public name_exprs {
|
|||
}
|
||||
|
||||
void gen_name_for_expr(expr * n, expr * & t, proof * & t_pr) {
|
||||
expr_ref new_def(m_manager);
|
||||
proof_ref new_def_pr(m_manager);
|
||||
expr_ref new_def(m);
|
||||
proof_ref new_def_pr(m);
|
||||
|
||||
if (m_defined_names.mk_name(n, new_def, new_def_pr, m_r, m_pr)) {
|
||||
m_def_exprs->push_back(new_def);
|
||||
if (m_manager.proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_def_proofs->push_back(new_def_pr);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class name_exprs_core : public name_exprs {
|
|||
}
|
||||
|
||||
bool get_subst(expr * s, expr * & t, proof * & t_pr) {
|
||||
TRACE("name_exprs", tout << "get_subst:\n" << mk_ismt2_pp(s, m_manager) << "\n";);
|
||||
TRACE("name_exprs", tout << "get_subst:\n" << mk_ismt2_pp(s, m) << "\n";);
|
||||
if (m_pred(s)) {
|
||||
gen_name_for_expr(s, t, t_pr);
|
||||
return true;
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
m_cfg.m_def_exprs = &new_defs;
|
||||
m_cfg.m_def_proofs = &new_def_proofs;
|
||||
m_rw(n, r, p);
|
||||
TRACE("name_exprs", tout << mk_ismt2_pp(n, m_rw.m()) << "\n---->\n" << mk_ismt2_pp(r, m_rw.m()) << "\n";);
|
||||
TRACE("name_exprs", tout << mk_ismt2_pp(n, m_rw.m()) << "\n---->\n" << r << "\n";);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,11 +99,11 @@ name_exprs * mk_expr_namer(ast_manager & m, defined_names & n, expr_predicate &
|
|||
|
||||
class name_quantifier_labels : public name_exprs_core {
|
||||
class pred : public expr_predicate {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
public:
|
||||
pred(ast_manager & m):m_manager(m) {}
|
||||
pred(ast_manager & m):m(m) {}
|
||||
bool operator()(expr * t) override {
|
||||
return is_quantifier(t) || m_manager.is_label(t);
|
||||
return is_quantifier(t) || m.is_label(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -124,16 +124,16 @@ name_exprs * mk_quantifier_label_namer(ast_manager & m, defined_names & n) {
|
|||
|
||||
class name_nested_formulas : public name_exprs_core {
|
||||
struct pred : public expr_predicate {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
expr * m_root;
|
||||
|
||||
pred(ast_manager & m):m_manager(m), m_root(nullptr) {}
|
||||
pred(ast_manager & m):m(m), m_root(0) {}
|
||||
|
||||
bool operator()(expr * t) override {
|
||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m_manager) << "\n";);
|
||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
if (is_app(t))
|
||||
return to_app(t)->get_family_id() == m_manager.get_basic_family_id() && to_app(t)->get_num_args() > 0 && t != m_root;
|
||||
return m_manager.is_label(t) || is_quantifier(t);
|
||||
return to_app(t)->get_family_id() == m.get_basic_family_id() && to_app(t)->get_num_args() > 0 && t != m_root;
|
||||
return m.is_label(t) || is_quantifier(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,16 +17,16 @@ Notes:
|
|||
Major revision on 2011-10-06
|
||||
|
||||
--*/
|
||||
|
||||
#include "util/warning.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/normal_forms/nnf.h"
|
||||
#include "ast/normal_forms/nnf_params.hpp"
|
||||
#include "util/warning.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
#include "ast/act_cache.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
|
@ -67,36 +67,42 @@ enum nnf_mode {
|
|||
class skolemizer {
|
||||
typedef act_cache cache;
|
||||
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
symbol m_sk_hack;
|
||||
bool m_sk_hack_enabled;
|
||||
cache m_cache;
|
||||
cache m_cache_pr;
|
||||
|
||||
void process(quantifier * q, expr_ref & r, proof_ref & p) {
|
||||
if (q->get_kind() == lambda_k) {
|
||||
TRACE("nnf", tout << expr_ref(q, m) << "\n";);
|
||||
r = q;
|
||||
p = nullptr;
|
||||
return;
|
||||
}
|
||||
used_vars uv;
|
||||
uv(q);
|
||||
SASSERT(is_well_sorted(m(), q));
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
unsigned sz = uv.get_max_found_var_idx_plus_1();
|
||||
ptr_buffer<sort> sorts;
|
||||
expr_ref_vector args(m());
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s != nullptr) {
|
||||
sorts.push_back(s);
|
||||
args.push_back(m().mk_var(i, s));
|
||||
args.push_back(m.mk_var(i, s));
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("skolemizer", tout << "skid: " << q->get_skid() << "\n";);
|
||||
|
||||
expr_ref_vector substitution(m());
|
||||
|
||||
expr_ref_vector substitution(m);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = num_decls; i > 0; ) {
|
||||
--i;
|
||||
sort * r = q->get_decl_sort(i);
|
||||
func_decl * sk_decl = m().mk_fresh_func_decl(q->get_decl_name(i), q->get_skid(), sorts.size(), sorts.c_ptr(), r);
|
||||
app * sk = m().mk_app(sk_decl, args.size(), args.c_ptr());
|
||||
func_decl * sk_decl = m.mk_fresh_func_decl(q->get_decl_name(i), q->get_skid(), sorts.size(), sorts.c_ptr(), r);
|
||||
app * sk = m.mk_app(sk_decl, args.size(), args.c_ptr());
|
||||
substitution.push_back(sk);
|
||||
}
|
||||
//
|
||||
|
@ -106,7 +112,7 @@ class skolemizer {
|
|||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s != nullptr)
|
||||
substitution.push_back(m().mk_var(i, s));
|
||||
substitution.push_back(m.mk_var(i, s));
|
||||
else
|
||||
substitution.push_back(nullptr);
|
||||
}
|
||||
|
@ -118,9 +124,9 @@ class skolemizer {
|
|||
//
|
||||
// (VAR 0) should be in the last position of substitution.
|
||||
//
|
||||
var_subst s(m());
|
||||
SASSERT(is_well_sorted(m(), q->get_expr()));
|
||||
expr_ref tmp(m());
|
||||
var_subst s(m);
|
||||
SASSERT(is_well_sorted(m, q->get_expr()));
|
||||
expr_ref tmp(m);
|
||||
expr * body = q->get_expr();
|
||||
if (m_sk_hack_enabled) {
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
|
@ -128,27 +134,27 @@ class skolemizer {
|
|||
expr * p = q->get_pattern(i);
|
||||
if (is_sk_hack(p)) {
|
||||
expr * sk_hack = to_app(p)->get_arg(0);
|
||||
if (q->is_forall()) // check whether is in negative/positive context.
|
||||
tmp = m().mk_or(body, m().mk_not(sk_hack)); // negative context
|
||||
if (q->get_kind() == forall_k) // check whether is in negative/positive context.
|
||||
tmp = m.mk_or(body, m.mk_not(sk_hack)); // negative context
|
||||
else
|
||||
tmp = m().mk_and(body, sk_hack); // positive context
|
||||
tmp = m.mk_and(body, sk_hack); // positive context
|
||||
body = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
s(body, substitution.size(), substitution.c_ptr(), r);
|
||||
r = s(body, substitution.size(), substitution.c_ptr());
|
||||
p = nullptr;
|
||||
if (m().proofs_enabled()) {
|
||||
if (q->is_forall())
|
||||
p = m().mk_skolemization(m().mk_not(q), m().mk_not(r));
|
||||
if (m.proofs_enabled()) {
|
||||
if (q->get_kind() == forall_k)
|
||||
p = m.mk_skolemization(m.mk_not(q), m.mk_not(r));
|
||||
else
|
||||
p = m().mk_skolemization(q, r);
|
||||
p = m.mk_skolemization(q, r);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
skolemizer(ast_manager & m):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_sk_hack("sk_hack"),
|
||||
m_sk_hack_enabled(false),
|
||||
m_cache(m),
|
||||
|
@ -159,25 +165,23 @@ public:
|
|||
m_sk_hack_enabled = f;
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
void operator()(quantifier * q, expr_ref & r, proof_ref & p) {
|
||||
r = m_cache.find(q);
|
||||
if (r.get() != nullptr) {
|
||||
p = nullptr;
|
||||
if (m().proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
p = static_cast<proof*>(m_cache_pr.find(q));
|
||||
}
|
||||
else {
|
||||
process(q, r, p);
|
||||
m_cache.insert(q, r);
|
||||
if (m().proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_cache_pr.insert(q, p);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_sk_hack(expr * p) const {
|
||||
SASSERT(m().is_pattern(p));
|
||||
SASSERT(m.is_pattern(p));
|
||||
if (to_app(p)->get_num_args() != 1)
|
||||
return false;
|
||||
expr * body = to_app(p)->get_arg(0);
|
||||
|
@ -186,7 +190,7 @@ public:
|
|||
func_decl * f = to_app(body)->get_decl();
|
||||
if (!(f->get_name() == m_sk_hack && f->get_arity() == 1))
|
||||
return false;
|
||||
if (!m().is_bool(body)) {
|
||||
if (!m.is_bool(body)) {
|
||||
warning_msg("sk_hack constant must return a Boolean");
|
||||
return false;
|
||||
}
|
||||
|
@ -233,8 +237,8 @@ struct nnf::imp {
|
|||
#define POS_NQ_CIDX 1 // positive polarity and not nested in a quantifier
|
||||
#define NEG_Q_CIDX 2 // negative polarity and nested in a quantifier
|
||||
#define POS_Q_CIDX 3 // positive polarity and nested in a quantifier
|
||||
|
||||
ast_manager & m_manager;
|
||||
|
||||
ast_manager & m;
|
||||
vector<frame> m_frame_stack;
|
||||
expr_ref_vector m_result_stack;
|
||||
|
||||
|
@ -263,7 +267,7 @@ struct nnf::imp {
|
|||
unsigned long long m_max_memory; // in bytes
|
||||
|
||||
imp(ast_manager & m, defined_names & n, params_ref const & p):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_result_stack(m),
|
||||
m_todo_defs(m),
|
||||
m_todo_proofs(m),
|
||||
|
@ -279,9 +283,9 @@ struct nnf::imp {
|
|||
m_name_quant = mk_quantifier_label_namer(m, n);
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
// ast_manager & m() const { return m; }
|
||||
|
||||
bool proofs_enabled() const { return m().proofs_enabled(); }
|
||||
bool proofs_enabled() const { return m.proofs_enabled(); }
|
||||
|
||||
~imp() {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
|
@ -334,7 +338,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m), pol, in_q, cache_res, m_result_stack.size()));
|
||||
}
|
||||
|
||||
static unsigned get_cache_idx(bool pol, bool in_q) {
|
||||
|
@ -382,8 +386,8 @@ struct nnf::imp {
|
|||
cooperate("nnf");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw nnf_exception(Z3_MAX_MEMORY_MSG);
|
||||
if (m().canceled())
|
||||
throw nnf_exception(m().limit().get_cancel_msg());
|
||||
if (m.canceled())
|
||||
throw nnf_exception(m.limit().get_cancel_msg());
|
||||
}
|
||||
|
||||
void set_new_child_flag() {
|
||||
|
@ -397,16 +401,16 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void skip(expr * t, bool pol) {
|
||||
expr * r = pol ? t : m().mk_not(t);
|
||||
expr * r = pol ? t : m.mk_not(t);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
m_result_pr_stack.push_back(m().mk_oeq_reflexivity(r));
|
||||
m_result_pr_stack.push_back(m.mk_oeq_reflexivity(r));
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
}
|
||||
}
|
||||
|
||||
bool visit(expr * t, bool pol, bool in_q) {
|
||||
SASSERT(m().is_bool(t));
|
||||
SASSERT(m.is_bool(t));
|
||||
|
||||
if (m_mode == NNF_SKOLEM || (m_mode == NNF_QUANT && !in_q)) {
|
||||
if (!has_quantifiers(t) && !has_labels(t)) {
|
||||
|
@ -456,12 +460,12 @@ struct nnf::imp {
|
|||
proof * mk_proof(bool pol, unsigned num_parents, proof * const * parents, app * old_e, app * new_e) {
|
||||
if (pol) {
|
||||
if (old_e->get_decl() == new_e->get_decl())
|
||||
return m().mk_oeq_congruence(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m().mk_nnf_pos(old_e, new_e, num_parents, parents);
|
||||
return m.mk_oeq_congruence(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m.mk_nnf_pos(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
else
|
||||
return m().mk_nnf_neg(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
return m.mk_nnf_neg(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
|
||||
bool process_and_or(app * t, frame & fr) {
|
||||
|
@ -473,11 +477,11 @@ struct nnf::imp {
|
|||
return false;
|
||||
}
|
||||
app * r;
|
||||
if (m().is_and(t) == fr.m_pol)
|
||||
r = m().mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
if (m.is_and(t) == fr.m_pol)
|
||||
r = m.mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
r = m.mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -500,7 +504,7 @@ struct nnf::imp {
|
|||
if (proofs_enabled()) {
|
||||
pr = m_result_pr_stack.back();
|
||||
if (!fr.m_pol) {
|
||||
pr = m().mk_nnf_neg(t, r, 1, &pr);
|
||||
pr = m.mk_nnf_neg(t, r, 1, &pr);
|
||||
m_result_pr_stack.pop_back();
|
||||
m_result_pr_stack.push_back(pr);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -526,10 +530,10 @@ struct nnf::imp {
|
|||
|
||||
app * r;
|
||||
if (fr.m_pol)
|
||||
r = m().mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
r = m.mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
r = m.mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -570,7 +574,7 @@ struct nnf::imp {
|
|||
expr * _then = rs[2];
|
||||
expr * _else = rs[3];
|
||||
|
||||
app * r = m().mk_and(m().mk_or(_not_cond, _then), m().mk_or(_cond, _else));
|
||||
app * r = m.mk_and(m.mk_or(_not_cond, _then), m.mk_or(_cond, _else));
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -582,7 +586,7 @@ struct nnf::imp {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_eq(app * t) const { return m().is_eq(t); }
|
||||
bool is_eq(app * t) const { return m.is_eq(t); }
|
||||
|
||||
bool process_iff_xor(app * t, frame & fr) {
|
||||
SASSERT(t->get_num_args() == 2);
|
||||
|
@ -614,10 +618,10 @@ struct nnf::imp {
|
|||
expr * not_rhs = rs[3];
|
||||
|
||||
app * r;
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
r = m().mk_and(m().mk_or(not_lhs, rhs), m().mk_or(lhs, not_rhs));
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
r = m.mk_and(m.mk_or(not_lhs, rhs), m.mk_or(lhs, not_rhs));
|
||||
else
|
||||
r = m().mk_and(m().mk_or(lhs, rhs), m().mk_or(not_lhs, not_rhs));
|
||||
r = m.mk_and(m.mk_or(lhs, rhs), m.mk_or(not_lhs, not_rhs));
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -630,7 +634,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_eq(app * t, frame & fr) {
|
||||
if (m().is_iff(t))
|
||||
if (m.is_bool(t->get_arg(0)))
|
||||
return process_iff_xor(t, fr);
|
||||
else
|
||||
return process_default(t, fr);
|
||||
|
@ -639,21 +643,20 @@ struct nnf::imp {
|
|||
bool process_default(app * t, frame & fr) {
|
||||
SASSERT(fr.m_i == 0);
|
||||
if (m_mode == NNF_FULL || t->has_quantifiers() || t->has_labels()) {
|
||||
expr_ref n2(m());
|
||||
proof_ref pr2(m());
|
||||
expr_ref n2(m);
|
||||
proof_ref pr2(m);
|
||||
if (m_mode == NNF_FULL || (m_mode != NNF_SKOLEM && fr.m_in_q))
|
||||
m_name_nested_formulas->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
else
|
||||
m_name_quant->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
|
||||
if (!fr.m_pol)
|
||||
n2 = m().mk_not(n2);
|
||||
|
||||
n2 = m.mk_not(n2);
|
||||
m_result_stack.push_back(n2);
|
||||
if (proofs_enabled()) {
|
||||
if (!fr.m_pol) {
|
||||
proof * prs[1] = { pr2 };
|
||||
pr2 = m().mk_oeq_congruence(m().mk_not(t), static_cast<app*>(n2.get()), 1, prs);
|
||||
pr2 = m.mk_oeq_congruence(m.mk_not(t), static_cast<app*>(n2.get()), 1, prs);
|
||||
}
|
||||
m_result_pr_stack.push_back(pr2);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -681,24 +684,24 @@ struct nnf::imp {
|
|||
|
||||
buffer<symbol> names;
|
||||
bool pos;
|
||||
m().is_label(t, pos, names);
|
||||
expr_ref r(m());
|
||||
proof_ref pr(m());
|
||||
m.is_label(t, pos, names);
|
||||
expr_ref r(m);
|
||||
proof_ref pr(m);
|
||||
if (fr.m_pol == pos) {
|
||||
expr * lbl_lit = m().mk_label_lit(names.size(), names.c_ptr());
|
||||
r = m().mk_and(arg, lbl_lit);
|
||||
expr * lbl_lit = m.mk_label_lit(names.size(), names.c_ptr());
|
||||
r = m.mk_and(arg, lbl_lit);
|
||||
if (proofs_enabled()) {
|
||||
expr_ref aux(m_manager);
|
||||
aux = m().mk_label(true, names.size(), names.c_ptr(), arg);
|
||||
pr = m().mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
|
||||
m().mk_iff_oeq(m().mk_rewrite(aux, r)));
|
||||
expr_ref aux(m);
|
||||
aux = m.mk_label(true, names.size(), names.c_ptr(), arg);
|
||||
pr = m.mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
|
||||
m.mk_iff_oeq(m.mk_rewrite(aux, r)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = arg;
|
||||
if (proofs_enabled()) {
|
||||
proof * p1 = m().mk_iff_oeq(m().mk_rewrite(t, t->get_arg(0)));
|
||||
pr = m().mk_transitivity(p1, arg_pr);
|
||||
proof * p1 = m.mk_iff_oeq(m.mk_rewrite(t, t->get_arg(0)));
|
||||
pr = m.mk_transitivity(p1, arg_pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,9 +716,9 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_app(app * t, frame & fr) {
|
||||
TRACE("nnf", tout << mk_ismt2_pp(t, m()) << "\n";);
|
||||
SASSERT(m().is_bool(t));
|
||||
if (t->get_family_id() == m().get_basic_family_id()) {
|
||||
TRACE("nnf", tout << mk_ismt2_pp(t, m) << "\n";);
|
||||
SASSERT(m.is_bool(t));
|
||||
if (t->get_family_id() == m.get_basic_family_id()) {
|
||||
switch (static_cast<basic_op_kind>(t->get_decl_kind())) {
|
||||
case OP_AND: case OP_OR:
|
||||
return process_and_or(t, fr);
|
||||
|
@ -734,7 +737,7 @@ struct nnf::imp {
|
|||
}
|
||||
}
|
||||
|
||||
if (m().is_label(t)) {
|
||||
if (m.is_label(t)) {
|
||||
return process_label(t, fr);
|
||||
}
|
||||
|
||||
|
@ -747,28 +750,51 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool process_quantifier(quantifier * q, frame & fr) {
|
||||
expr_ref r(m());
|
||||
proof_ref pr(m());
|
||||
TRACE("nnf", tout << expr_ref(q, m) << "\n";);
|
||||
expr_ref r(m);
|
||||
proof_ref pr(m);
|
||||
if (fr.m_i == 0) {
|
||||
fr.m_i = 1;
|
||||
if (q->is_forall() == fr.m_pol || !m_skolemize) {
|
||||
if (is_lambda(q)) {
|
||||
if (!visit(q->get_expr(), fr.m_pol, true))
|
||||
return false;
|
||||
}
|
||||
else if (is_forall(q) == fr.m_pol || !m_skolemize) {
|
||||
if (!visit(q->get_expr(), fr.m_pol, true))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
m_skolemizer(q, r, pr);
|
||||
if (!visit(r, !q->is_forall(), fr.m_in_q))
|
||||
if (!visit(r, !is_forall(q), fr.m_in_q))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (q->is_forall() == fr.m_pol || !m_skolemize) {
|
||||
if (is_lambda(q)) {
|
||||
expr * new_expr = m_result_stack.back();
|
||||
quantifier * new_q = m.update_quantifier(q, new_expr);
|
||||
proof * new_q_pr = nullptr;
|
||||
if (proofs_enabled()) {
|
||||
// proof * new_expr_pr = m_result_pr_stack.back();
|
||||
new_q_pr = m.mk_rewrite(q, new_q); // TBD use new_expr_pr
|
||||
}
|
||||
|
||||
m_result_stack.pop_back();
|
||||
m_result_stack.push_back(new_q);
|
||||
if (proofs_enabled()) {
|
||||
m_result_pr_stack.pop_back();
|
||||
m_result_pr_stack.push_back(new_q_pr);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (is_forall(q) == fr.m_pol || !m_skolemize) {
|
||||
expr * new_expr = m_result_stack.back();
|
||||
proof * new_expr_pr = proofs_enabled() ? m_result_pr_stack.back() : nullptr;
|
||||
|
||||
ptr_buffer<expr> new_patterns;
|
||||
|
||||
if (q->is_forall() == fr.m_pol) {
|
||||
if (is_forall(q) == fr.m_pol) {
|
||||
// collect non sk_hack patterns
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
|
@ -785,14 +811,19 @@ struct nnf::imp {
|
|||
quantifier * new_q = nullptr;
|
||||
proof * new_q_pr = nullptr;
|
||||
if (fr.m_pol) {
|
||||
new_q = m().update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled())
|
||||
new_q_pr = m().mk_nnf_pos(q, new_q, 1, &new_expr_pr);
|
||||
new_q = m.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled()) {
|
||||
new_expr_pr = m.mk_bind_proof(q, new_expr_pr);
|
||||
new_q_pr = m.mk_nnf_pos(q, new_q, 1, &new_expr_pr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_q = m().update_quantifier(q, !q->is_forall(), new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled())
|
||||
new_q_pr = m().mk_nnf_neg(q, new_q, 1, &new_expr_pr);
|
||||
quantifier_kind k = is_forall(q)? exists_k : forall_k;
|
||||
new_q = m.update_quantifier(q, k, new_patterns.size(), new_patterns.c_ptr(), new_expr);
|
||||
if (proofs_enabled()) {
|
||||
new_expr_pr = m.mk_bind_proof(q, new_expr_pr);
|
||||
new_q_pr = m.mk_nnf_neg(q, new_q, 1, &new_expr_pr);
|
||||
}
|
||||
}
|
||||
|
||||
m_result_stack.pop_back();
|
||||
|
@ -809,7 +840,7 @@ struct nnf::imp {
|
|||
// However, the proof must be updated
|
||||
if (proofs_enabled()) {
|
||||
m_skolemizer(q, r, pr); // retrieve the proof
|
||||
pr = m().mk_transitivity(pr, m_result_pr_stack.back());
|
||||
pr = m.mk_transitivity(pr, m_result_pr_stack.back());
|
||||
m_result_pr_stack.pop_back();
|
||||
m_result_pr_stack.push_back(pr);
|
||||
SASSERT(m_result_stack.size() == m_result_pr_stack.size());
|
||||
|
@ -827,14 +858,14 @@ struct nnf::imp {
|
|||
result_pr = m_result_pr_stack.back();
|
||||
m_result_pr_stack.pop_back();
|
||||
if (result_pr.get() == nullptr)
|
||||
result_pr = m().mk_reflexivity(t);
|
||||
result_pr = m.mk_reflexivity(t);
|
||||
SASSERT(m_result_pr_stack.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void process(expr * t, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("nnf", tout << "processing:\n" << mk_ismt2_pp(t, m()) << "\n";);
|
||||
SASSERT(m().is_bool(t));
|
||||
TRACE("nnf", tout << "processing:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
SASSERT(m.is_bool(t));
|
||||
|
||||
if (visit(t, true /* positive polarity */, false /* not nested in quantifier */)) {
|
||||
recover_result(t, result, result_pr);
|
||||
|
@ -883,13 +914,13 @@ struct nnf::imp {
|
|||
unsigned old_sz2 = new_def_proofs.size();
|
||||
|
||||
for (unsigned i = 0; i < m_todo_defs.size(); i++) {
|
||||
expr_ref dr(m());
|
||||
proof_ref dpr(m());
|
||||
expr_ref dr(m);
|
||||
proof_ref dpr(m);
|
||||
process(m_todo_defs.get(i), dr, dpr);
|
||||
new_defs.push_back(dr);
|
||||
if (proofs_enabled()) {
|
||||
proof * new_pr = m().mk_modus_ponens(m_todo_proofs.get(i), dpr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
proof * new_pr = m.mk_modus_ponens(m_todo_proofs.get(i), dpr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
}
|
||||
}
|
||||
std::reverse(new_defs.c_ptr() + old_sz1, new_defs.c_ptr() + new_defs.size());
|
||||
|
@ -909,7 +940,7 @@ nnf::~nnf() {
|
|||
|
||||
void nnf::operator()(expr * n, expr_ref_vector & new_defs, proof_ref_vector & new_def_proofs, expr_ref & r, proof_ref & p) {
|
||||
m_imp->operator()(n, new_defs, new_def_proofs, r, p);
|
||||
TRACE("nnf_result", tout << mk_ismt2_pp(n, m_imp->m()) << "\nNNF result:\n" << mk_ismt2_pp(r, m_imp->m()) << "\n";);
|
||||
TRACE("nnf_result", tout << expr_ref(n, r.get_manager()) << "\nNNF result:\n" << new_defs << "\n" << r << "\n";);
|
||||
}
|
||||
|
||||
void nnf::updt_params(params_ref const & p) {
|
||||
|
|
|
@ -49,7 +49,8 @@ struct pull_quant::imp {
|
|||
if (is_quantifier(child)) {
|
||||
quantifier * q = to_quantifier(child);
|
||||
expr * body = q->get_expr();
|
||||
result = m_manager.update_quantifier(q, !q->is_forall(), m_manager.mk_not(body));
|
||||
quantifier_kind k = q->get_kind() == forall_k ? exists_k : forall_k;
|
||||
result = m_manager.update_quantifier(q, k, m_manager.mk_not(body));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -149,7 +150,7 @@ struct pull_quant::imp {
|
|||
// 3) MBQI
|
||||
std::reverse(var_sorts.begin(), var_sorts.end());
|
||||
std::reverse(var_names.begin(), var_names.end());
|
||||
result = m_manager.mk_quantifier(forall_children,
|
||||
result = m_manager.mk_quantifier(forall_children ? forall_k : exists_k,
|
||||
var_sorts.size(),
|
||||
var_sorts.c_ptr(),
|
||||
var_names.c_ptr(),
|
||||
|
@ -220,9 +221,7 @@ struct pull_quant::imp {
|
|||
expr_ref_buffer new_args(m_manager);
|
||||
expr_ref new_arg(m_manager);
|
||||
ptr_buffer<proof> proofs;
|
||||
unsigned num = to_app(n)->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * arg = to_app(n)->get_arg(i);
|
||||
for (expr * arg : *to_app(n)) {
|
||||
pull_quant1(arg , new_arg);
|
||||
new_args.push_back(new_arg);
|
||||
if (new_arg != arg)
|
||||
|
@ -277,10 +276,13 @@ struct pull_quant::imp {
|
|||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
if (old_q->is_exists()) {
|
||||
if (is_exists(old_q)) {
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_forall(new_body))
|
||||
return false;
|
||||
|
|
|
@ -53,7 +53,7 @@ expr_pattern_match::match_quantifier(quantifier* qf, app_ref_vector& patterns, u
|
|||
m_regs[0] = qf->get_expr();
|
||||
for (unsigned i = 0; i < m_precompiled.size(); ++i) {
|
||||
quantifier* qf2 = m_precompiled[i].get();
|
||||
if (qf2->is_forall() != qf->is_forall()) {
|
||||
if (qf2->get_kind() != qf->get_kind() || is_lambda(qf)) {
|
||||
continue;
|
||||
}
|
||||
if (qf2->get_num_decls() != qf->get_num_decls()) {
|
||||
|
|
|
@ -582,7 +582,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
proof_ref & result_pr) {
|
||||
|
||||
TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m) << "\n";);
|
||||
if (!q->is_forall()) {
|
||||
if (!is_forall(q)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -673,6 +673,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
new_q = m.update_quantifier_weight(new_q, weight);
|
||||
if (m.proofs_enabled()) {
|
||||
proof* new_body_pr = m.mk_reflexivity(new_body);
|
||||
new_body_pr = m.mk_bind_proof(new_q, new_body_pr);
|
||||
result_pr = m.mk_quant_intro(q, new_q, new_body_pr);
|
||||
}
|
||||
|
||||
|
@ -690,7 +691,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
}
|
||||
new_q = m.update_quantifier(result2, new_patterns.size(), (expr**) new_patterns.c_ptr(), result2->get_expr());
|
||||
if (m.proofs_enabled()) {
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_reflexivity(new_q->get_expr())));
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_bind_proof(new_q, m.mk_reflexivity(new_q->get_expr()))));
|
||||
}
|
||||
TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";);
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
to_quantifier(t1.get())->get_expr() == s1.get() &&
|
||||
to_quantifier(t2.get())->get_expr() == s2.get() &&
|
||||
to_quantifier(t1.get())->get_num_decls() == to_quantifier(t2.get())->get_num_decls() &&
|
||||
to_quantifier(t1.get())->is_forall() == to_quantifier(t2.get())->is_forall()) {
|
||||
to_quantifier(t1.get())->get_kind() == to_quantifier(t2.get())->get_kind()) {
|
||||
quantifier* q1 = to_quantifier(t1.get());
|
||||
quantifier* q2 = to_quantifier(t2.get());
|
||||
for (unsigned i = 0; i < q1->get_num_decls(); ++i) {
|
||||
|
@ -734,9 +734,10 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
is_forall = true;
|
||||
}
|
||||
if (is_quantifier(e)) {
|
||||
q = to_quantifier(e);
|
||||
SASSERT(!is_lambda(e));
|
||||
q = to_quantifier(e);
|
||||
// TBD check that quantifier is properly instantiated
|
||||
return is_forall == q->is_forall();
|
||||
return is_forall == ::is_forall(q);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -784,7 +785,7 @@ bool proof_checker::check1_basic(proof* p, expr_ref_vector& side_conditions) {
|
|||
// SASSERT(to_quantifier(premise)->get_num_decls() == sub.size());
|
||||
premise = to_quantifier(premise)->get_expr();
|
||||
}
|
||||
vs(premise, sub.size(), sub.c_ptr(), premise);
|
||||
premise = vs(premise, sub.size(), sub.c_ptr());
|
||||
}
|
||||
fmls.push_back(premise.get());
|
||||
TRACE("proof_checker",
|
||||
|
@ -974,7 +975,7 @@ bool proof_checker::match_app(expr const* e, func_decl_ref& d, expr_ref_vector&
|
|||
bool proof_checker::match_quantifier(expr const* e, bool& is_univ, sort_ref_vector& sorts, expr_ref& body) const {
|
||||
if (is_quantifier(e)) {
|
||||
quantifier const* q = to_quantifier(e);
|
||||
is_univ = q->is_forall();
|
||||
is_univ = is_forall(q);
|
||||
body = q->get_expr();
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
sorts.push_back(q->get_decl_sort(i));
|
||||
|
|
|
@ -975,9 +975,7 @@ private:
|
|||
|
||||
void compose(expr_ref_vector& sub, expr_ref_vector const& s0) {
|
||||
for (unsigned i = 0; i < sub.size(); ++i) {
|
||||
expr_ref e(m);
|
||||
var_subst(m, false)(sub[i].get(), s0.size(), s0.c_ptr(), e);
|
||||
sub[i] = e;
|
||||
sub[i] = var_subst(m, false)(sub[i].get(), s0.size(), s0.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -995,7 +993,7 @@ private:
|
|||
tout << sub.size() << "\n";);
|
||||
return;
|
||||
}
|
||||
var_subst(m, false)(q->get_expr(), sub.size(), sub.c_ptr(), fml);
|
||||
fml = var_subst(m, false)(q->get_expr(), sub.size(), sub.c_ptr());
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include "ast/rewriter/array_rewriter_params.hpp"
|
||||
#include "ast/ast_lt.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
void array_rewriter::updt_params(params_ref const & _p) {
|
||||
array_rewriter_params p(_p);
|
||||
|
@ -196,6 +197,17 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
|
|||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (is_lambda(args[0])) {
|
||||
// anywhere lambda reduction as opposed to whnf
|
||||
// select(lambda(X) M, N) -> M[N/X]
|
||||
quantifier* q = to_quantifier(args[0]);
|
||||
SASSERT(q->get_num_decls() == num_args - 1);
|
||||
var_subst subst(m());
|
||||
result = subst(q->get_expr(), num_args - 1, args + 1);
|
||||
return BR_REWRITE_FULL;
|
||||
|
||||
}
|
||||
|
||||
if (m_util.is_as_array(args[0])) {
|
||||
// select(as-array[f], I) --> f(I)
|
||||
func_decl * f = m_util.get_as_array_func_decl(to_app(args[0]));
|
||||
|
|
|
@ -636,7 +636,7 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
|
|||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
result = m().mk_quantifier(old_q->get_kind(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = nullptr;
|
||||
|
|
|
@ -588,58 +588,39 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
VERIFY(m().is_ite(ite, cond, t, e));
|
||||
SASSERT(m().is_value(val));
|
||||
|
||||
if (m().is_value(t) && m().is_value(e)) {
|
||||
if (t != val && e != val) {
|
||||
TRACE("try_ite_value", tout << mk_ismt2_pp(t, m()) << " " << mk_ismt2_pp(e, m()) << " " << mk_ismt2_pp(val, m()) << "\n";
|
||||
tout << t << " " << e << " " << val << "\n";);
|
||||
result = m().mk_false();
|
||||
}
|
||||
else if (t == val && e == val) {
|
||||
if (m().are_distinct(val, e)) {
|
||||
result = m().mk_and(m().mk_eq(t, val), cond);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_distinct(val, t)) {
|
||||
result = m().mk_and(m().mk_eq(e, val), m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_equal(val, t)) {
|
||||
if (m().are_equal(val, e)) {
|
||||
result = m().mk_true();
|
||||
}
|
||||
else if (t == val) {
|
||||
result = cond;
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
SASSERT(e == val);
|
||||
mk_not(cond, result);
|
||||
result = m().mk_or(m().mk_eq(e, val), cond);
|
||||
}
|
||||
return BR_DONE;
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m_ite_extra_rules) {
|
||||
if (m().is_value(t)) {
|
||||
if (val == t) {
|
||||
result = m().mk_or(cond, m().mk_eq(val, e));
|
||||
}
|
||||
else {
|
||||
mk_not(cond, result);
|
||||
result = m().mk_and(result, m().mk_eq(val, e));
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_value(e)) {
|
||||
if (val == e) {
|
||||
mk_not(cond, result);
|
||||
result = m().mk_or(result, m().mk_eq(val, t));
|
||||
}
|
||||
else {
|
||||
result = m().mk_and(cond, m().mk_eq(val, t));
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_equal(val, e)) {
|
||||
result = m().mk_or(m().mk_eq(t, val), m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
{
|
||||
expr* cond2, *t2, *e2;
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(t), val, result);
|
||||
result = m().mk_ite(cond, result, m().mk_eq(e, val));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(e), val, result);
|
||||
result = m().mk_ite(cond, m().mk_eq(t, val), result);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr;
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(t), val, result);
|
||||
result = m().mk_ite(cond, result, m().mk_eq(e, val));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
try_ite_value(to_app(e), val, result);
|
||||
result = m().mk_ite(cond, m().mk_eq(t, val), result);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
|
|
@ -87,20 +87,16 @@ bool bv_elim_cfg::reduce_quantifier(quantifier * q,
|
|||
expr* const* sub = subst_map.c_ptr();
|
||||
unsigned sub_size = subst_map.size();
|
||||
|
||||
subst(old_body, sub_size, sub, new_body);
|
||||
new_body = subst(old_body, sub_size, sub);
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref pat(m);
|
||||
subst(new_patterns[j], sub_size, sub, pat);
|
||||
pats.push_back(pat);
|
||||
pats.push_back(subst(new_patterns[j], sub_size, sub));
|
||||
}
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref nopat(m);
|
||||
subst(new_no_patterns[j], sub_size, sub, nopat);
|
||||
no_pats.push_back(nopat);
|
||||
no_pats.push_back(subst(new_no_patterns[j], sub_size, sub));
|
||||
}
|
||||
|
||||
result = m.mk_quantifier(true,
|
||||
result = m.mk_quantifier(forall_k,
|
||||
names.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
|
|
|
@ -133,7 +133,7 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
// Eliminate variables that have become unused
|
||||
if (reduced && is_forall(r)) {
|
||||
quantifier * q = to_quantifier(r);
|
||||
elim_unused_vars(m_manager, q, params_ref(), r);
|
||||
r = elim_unused_vars(m_manager, q, params_ref());
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * p1 = m_manager.mk_elim_unused_vars(q, r);
|
||||
pr = m_manager.mk_transitivity(pr, p1);
|
||||
|
@ -343,8 +343,7 @@ void der::create_substitution(unsigned sz) {
|
|||
expr_ref cur(m_map[m_order[i]], m_manager);
|
||||
|
||||
// do all the previous substitutions before inserting
|
||||
expr_ref r(m_manager);
|
||||
m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr(), r);
|
||||
expr_ref r = m_subst(cur, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
unsigned inx = sz - m_order[i]- 1;
|
||||
SASSERT(m_subst_map[inx]==0);
|
||||
|
@ -369,21 +368,18 @@ void der::apply_substitution(quantifier * q, expr_ref & r) {
|
|||
unsigned sz = m_new_args.size();
|
||||
expr_ref t(m_manager);
|
||||
t = (sz == 1) ? m_new_args[0] : m_manager.mk_or(sz, m_new_args.c_ptr());
|
||||
expr_ref new_e(m_manager);
|
||||
m_subst(t, m_subst_map.size(), m_subst_map.c_ptr(), new_e);
|
||||
expr_ref new_e = m_subst(t, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m_manager);
|
||||
expr_ref_buffer new_no_patterns(m_manager);
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref new_pat(m_manager);
|
||||
m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_pat);
|
||||
expr_ref new_pat = m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_patterns.push_back(new_pat);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref new_nopat(m_manager);
|
||||
m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr(), new_nopat);
|
||||
expr_ref new_nopat = m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ void distribute_forall::reduce1_app(app * a) {
|
|||
|
||||
void distribute_forall::reduce1_quantifier(quantifier * q) {
|
||||
// This transformation is applied after skolemization/quantifier elimination. So, all quantifiers are universal.
|
||||
SASSERT(q->is_forall());
|
||||
SASSERT(q->get_kind() == forall_k);
|
||||
|
||||
// This transformation is applied after basic pre-processing steps.
|
||||
// So, we can assume that
|
||||
|
@ -126,8 +126,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
|
|||
br.mk_not(arg, not_arg);
|
||||
quantifier_ref tmp_q(m_manager);
|
||||
tmp_q = m_manager.update_quantifier(q, not_arg);
|
||||
expr_ref new_q(m_manager);
|
||||
elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
|
||||
expr_ref new_q = elim_unused_vars(m_manager, tmp_q, params_ref());
|
||||
new_args.push_back(new_q);
|
||||
}
|
||||
expr_ref result(m_manager);
|
||||
|
|
|
@ -114,7 +114,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (!q->is_forall()) {
|
||||
if (!is_forall(q)) {
|
||||
return false;
|
||||
}
|
||||
unsigned num_vars = q->get_num_decls();
|
||||
|
@ -194,7 +194,7 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q,
|
|||
}
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(q, new_body);
|
||||
elim_unused_vars(m, new_q, params_ref(), result);
|
||||
result = elim_unused_vars(m, new_q, params_ref());
|
||||
result_pr = m.mk_rewrite(q, result);
|
||||
TRACE("elim_bounds", tout << mk_pp(q, m) << "\n" << result << "\n";);
|
||||
return true;
|
||||
|
|
|
@ -159,6 +159,8 @@ struct enum2bv_rewriter::imp {
|
|||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
if (q->get_kind() == lambda_k) return false;
|
||||
m_sorts.reset();
|
||||
expr_ref_vector bounds(m);
|
||||
bool found = false;
|
||||
|
@ -182,15 +184,20 @@ struct enum2bv_rewriter::imp {
|
|||
}
|
||||
expr_ref new_body_ref(old_body, m), tmp(m);
|
||||
if (!bounds.empty()) {
|
||||
if (q->is_forall()) {
|
||||
switch (q->get_kind()) {
|
||||
case forall_k:
|
||||
new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case exists_k:
|
||||
bounds.push_back(new_body_ref);
|
||||
new_body_ref = mk_and(bounds);
|
||||
break;
|
||||
case lambda_k:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = m.mk_quantifier(q->is_forall(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
||||
result = m.mk_quantifier(q->get_kind(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
||||
q->get_weight(), q->get_qid(), q->get_skid(),
|
||||
q->get_num_patterns(), new_patterns,
|
||||
q->get_num_no_patterns(), new_no_patterns);
|
||||
|
|
|
@ -32,7 +32,7 @@ bool simplify_inj_axiom(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
expr* arg1 = nullptr, * arg2 = nullptr, *narg = nullptr;
|
||||
expr* app1 = nullptr, * app2 = nullptr;
|
||||
expr* var1 = nullptr, * var2 = nullptr;
|
||||
if (q->is_forall() && m.is_or(n, arg1, arg2)) {
|
||||
if (is_forall(q) && m.is_or(n, arg1, arg2)) {
|
||||
if (m.is_not(arg2))
|
||||
std::swap(arg1, arg2);
|
||||
if (m.is_not(arg1, narg) &&
|
||||
|
|
|
@ -79,12 +79,12 @@ public:
|
|||
vars.push_back(a);
|
||||
}
|
||||
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
|
||||
instantiate(m, q, exprs, result);
|
||||
result = instantiate(m, q, exprs);
|
||||
}
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
|
||||
unsigned pull_quantifier(bool _is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names, bool use_fresh, bool rewrite_ok) {
|
||||
unsigned index = var_counter().get_next_var(fml);
|
||||
while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
|
||||
while (is_quantifier(fml) && _is_forall == is_forall(fml)) {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
index += q->get_num_decls();
|
||||
if (names) {
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
return index;
|
||||
}
|
||||
app_ref_vector vars(m);
|
||||
pull_quantifier(is_forall, fml, vars, use_fresh, rewrite_ok);
|
||||
pull_quantifier(_is_forall, fml, vars, use_fresh, rewrite_ok);
|
||||
if (vars.empty()) {
|
||||
return index;
|
||||
}
|
||||
|
@ -277,12 +277,16 @@ private:
|
|||
}
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
expr_ref tmp(m);
|
||||
if (!is_compatible(qt, q->is_forall())) {
|
||||
if (is_lambda(q)) {
|
||||
result = fml;
|
||||
break;
|
||||
}
|
||||
set_quantifier_type(qt, q->is_forall());
|
||||
expr_ref tmp(m);
|
||||
if (!is_compatible(qt, is_forall(q))) {
|
||||
result = fml;
|
||||
break;
|
||||
}
|
||||
set_quantifier_type(qt, is_forall(q));
|
||||
extract_quantifier(q, vars, tmp, use_fresh);
|
||||
pull_quantifier(tmp, qt, vars, result, use_fresh, rewrite_ok);
|
||||
break;
|
||||
|
|
|
@ -208,12 +208,10 @@ void rewriter_core::cleanup() {
|
|||
|
||||
#ifdef _TRACE
|
||||
void rewriter_core::display_stack(std::ostream & out, unsigned pp_depth) {
|
||||
svector<frame>::iterator it = m_frame_stack.begin();
|
||||
svector<frame>::iterator end = m_frame_stack.end();
|
||||
for (; it != end; ++it) {
|
||||
out << mk_bounded_pp(it->m_curr, m(), pp_depth) << "\n";
|
||||
out << "state: " << it->m_state << "\n";
|
||||
out << "cache: " << it->m_cache_result << ", new_child: " << it->m_new_child << ", max-depth: " << it->m_max_depth << ", i: " << it->m_i << "\n";
|
||||
for (frame& f : m_frame_stack) {
|
||||
out << mk_bounded_pp(f.m_curr, m(), pp_depth) << "\n";
|
||||
out << "state: " << f.m_state << "\n";
|
||||
out << "cache: " << f.m_cache_result << ", new_child: " << f.m_new_child << ", max-depth: " << f.m_max_depth << ", i: " << f.m_i << "\n";
|
||||
out << "------------------\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -350,11 +350,13 @@ public:
|
|||
void update_inv_binding_at(unsigned i, expr* binding);
|
||||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
void operator()(expr * t, expr_ref & result) { operator()(t, result, m_pr); }
|
||||
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
|
||||
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
|
||||
expr_ref result(m());
|
||||
SASSERT(!m_proof_gen);
|
||||
reset();
|
||||
set_inv_bindings(num_bindings, bindings);
|
||||
operator()(n, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void resume(expr_ref & result, proof_ref & result_pr);
|
||||
|
|
|
@ -542,7 +542,7 @@ void rewriter_tpl<Config>::process_quantifier(quantifier * q, frame & fr) {
|
|||
}
|
||||
result_stack().shrink(fr.m_spos);
|
||||
result_stack().push_back(m_r.get());
|
||||
SASSERT(m().is_bool(m_r));
|
||||
SASSERT(m().get_sort(q) == m().get_sort(m_r));
|
||||
if (!ProofGen) {
|
||||
SASSERT(num_decls <= m_bindings.size());
|
||||
m_bindings.shrink(m_bindings.size() - num_decls);
|
||||
|
|
|
@ -36,7 +36,7 @@ expr_ref sym_expr::accept(expr* e) {
|
|||
switch (m_ty) {
|
||||
case t_pred: {
|
||||
var_subst subst(m);
|
||||
subst(m_t, 1, &e, result);
|
||||
result = subst(m_t, 1, &e);
|
||||
break;
|
||||
}
|
||||
case t_char:
|
||||
|
|
|
@ -16,6 +16,7 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_params.hpp"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
|
@ -28,10 +29,9 @@ Notes:
|
|||
#include "ast/rewriter/pb_rewriter.h"
|
||||
#include "ast/rewriter/seq_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/well_sorted.h"
|
||||
|
||||
|
@ -606,7 +606,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
quantifier_ref q1(m());
|
||||
proof * p1 = nullptr;
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == old_q->is_forall() &&
|
||||
to_quantifier(new_body)->get_kind() == old_q->get_kind() &&
|
||||
to_quantifier(new_body)->get_kind() != lambda_k &&
|
||||
!old_q->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
@ -619,7 +620,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
|
||||
names.append(nested_q->get_num_decls(), nested_q->get_decl_names());
|
||||
|
||||
q1 = m().mk_quantifier(old_q->is_forall(),
|
||||
q1 = m().mk_quantifier(old_q->get_kind(),
|
||||
sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
|
@ -653,17 +654,19 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
SASSERT(is_well_sorted(m(), q1));
|
||||
}
|
||||
|
||||
elim_unused_vars(m(), q1, params_ref(), result);
|
||||
SASSERT(m().get_sort(old_q) == m().get_sort(q1));
|
||||
result = elim_unused_vars(m(), q1, params_ref());
|
||||
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
|
||||
result_pr = nullptr;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * p2 = nullptr;
|
||||
if (q1.get() != result.get())
|
||||
if (q1.get() != result.get() && q1->get_kind() != lambda_k)
|
||||
p2 = m().mk_elim_unused_vars(q1, result);
|
||||
result_pr = m().mk_transitivity(p1, p2);
|
||||
}
|
||||
SASSERT(m().get_sort(old_q) == m().get_sort(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -784,8 +787,8 @@ void th_rewriter::operator()(expr * t, expr_ref & result, proof_ref & result_pr)
|
|||
m_imp->operator()(t, result, result_pr);
|
||||
}
|
||||
|
||||
void th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result) {
|
||||
m_imp->operator()(n, num_bindings, bindings, result);
|
||||
expr_ref th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
|
||||
return m_imp->operator()(n, num_bindings, bindings);
|
||||
}
|
||||
|
||||
void th_rewriter::set_substitution(expr_substitution * s) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
void operator()(expr_ref& term);
|
||||
void operator()(expr * t, expr_ref & result);
|
||||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result);
|
||||
expr_ref operator()(expr * n, unsigned num_bindings, expr * const * bindings);
|
||||
|
||||
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args);
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ Notes:
|
|||
#include "ast/well_sorted.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
|
||||
void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) {
|
||||
expr_ref result(m_reducer.m());
|
||||
if (is_ground(n)) {
|
||||
result = n;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
SASSERT(is_well_sorted(result.m(), n));
|
||||
m_reducer.reset();
|
||||
|
@ -41,6 +42,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m_reducer.m()) << "\n";
|
||||
tout << "\n------>\n";
|
||||
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
|
||||
|
@ -49,16 +51,22 @@ unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const
|
|||
m_ignore_patterns_on_ground_qbody = m_params.get_bool("ignore_patterns_on_ground_qbody", true);
|
||||
}
|
||||
|
||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
||||
expr_ref unused_vars_eliminator::operator()(quantifier* q) {
|
||||
expr_ref result(m);
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
TRACE("elim_unused_vars", tout << expr_ref(q, m) << "\n";);
|
||||
if (is_lambda(q)) {
|
||||
result = q;
|
||||
return result;
|
||||
}
|
||||
if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
|
||||
// Ignore patterns if the body is a ground formula.
|
||||
result = q->get_expr();
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
if (!q->may_have_unused_vars()) {
|
||||
result = q;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
m_used.reset();
|
||||
m_used.process(q->get_expr());
|
||||
|
@ -73,7 +81,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
if (m_used.uses_all_vars(num_decls)) {
|
||||
q->set_no_unused_vars();
|
||||
result = q;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
ptr_buffer<sort> used_decl_sorts;
|
||||
|
@ -120,11 +128,11 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
|
||||
expr_ref new_expr(m);
|
||||
|
||||
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
new_expr = m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr());
|
||||
|
||||
if (num_removed == num_decls) {
|
||||
result = new_expr;
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref tmp(m);
|
||||
|
@ -132,15 +140,15 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
expr_ref_buffer new_no_patterns(m);
|
||||
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
tmp = m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr());
|
||||
new_patterns.push_back(tmp);
|
||||
}
|
||||
for (unsigned i = 0; i < num_no_patterns; i++) {
|
||||
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
tmp = m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr());
|
||||
new_no_patterns.push_back(tmp);
|
||||
}
|
||||
|
||||
result = m.mk_quantifier(q->is_forall(),
|
||||
result = m.mk_quantifier(q->get_kind(),
|
||||
used_decl_sorts.size(),
|
||||
used_decl_sorts.c_ptr(),
|
||||
used_decl_names.c_ptr(),
|
||||
|
@ -154,24 +162,28 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
new_no_patterns.c_ptr());
|
||||
to_quantifier(result)->set_no_unused_vars();
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
|
||||
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params) {
|
||||
unused_vars_eliminator el(m, params);
|
||||
el(q, result);
|
||||
expr_ref result = el(q);
|
||||
TRACE("elim_unused_vars", tout << expr_ref(q, m) << " -> " << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
|
||||
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs) {
|
||||
var_subst subst(m);
|
||||
expr_ref new_expr(m);
|
||||
subst(q->get_expr(), q->get_num_decls(), exprs, new_expr);
|
||||
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << mk_pp(new_expr, m) << "\n";);
|
||||
expr_ref new_expr(m), result(m);
|
||||
new_expr = subst(q->get_expr(), q->get_num_decls(), exprs);
|
||||
TRACE("var_subst", tout << mk_pp(q, m) << "\n" << new_expr << "\n";);
|
||||
inv_var_shifter shift(m);
|
||||
shift(new_expr, q->get_num_decls(), result);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
TRACE("instantiate_bug", tout << mk_ismt2_pp(q, m) << "\nusing\n";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); i++) tout << mk_ismt2_pp(exprs[i], m) << "\n";
|
||||
tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
Otherwise, (VAR 0) is stored in the first position, (VAR 1) in the second, and so on.
|
||||
*/
|
||||
void operator()(expr * n, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
expr_ref operator()(expr * n, unsigned num_args, expr * const * args);
|
||||
void reset() { m_reducer.reset(); }
|
||||
};
|
||||
|
||||
|
@ -63,10 +63,10 @@ class unused_vars_eliminator {
|
|||
bool m_ignore_patterns_on_ground_qbody;
|
||||
public:
|
||||
unused_vars_eliminator(ast_manager & m, params_ref const & params);
|
||||
void operator()(quantifier* q, expr_ref& r);
|
||||
expr_ref operator()(quantifier* q);
|
||||
};
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
|
||||
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params);
|
||||
|
||||
/**
|
||||
\brief Instantiate quantifier q using the given exprs.
|
||||
|
@ -77,7 +77,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params
|
|||
...
|
||||
(VAR (q->get_num_decls() - 1)) is stored in the first position of the array.
|
||||
*/
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result);
|
||||
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs);
|
||||
|
||||
/**
|
||||
\brief Enumerate set of free variables in expression.
|
||||
|
|
|
@ -35,9 +35,10 @@ struct well_sorted_proc {
|
|||
|
||||
void operator()(quantifier * n) {
|
||||
expr const * e = n->get_expr();
|
||||
if (!m_manager.is_bool(e)) {
|
||||
if (!is_lambda(n) && !m_manager.is_bool(e)) {
|
||||
warning_msg("quantifier's body must be a boolean.");
|
||||
m_error = true;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1070,7 +1070,7 @@ void cmd_context::mk_app(symbol const & s, unsigned num_args, expr * const * arg
|
|||
tout << "body:\n" << mk_ismt2_pp(_t, m()) << "\n";
|
||||
tout << "args:\n"; for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m()) << "\n" << mk_pp(m().get_sort(args[i]), m()) << "\n";);
|
||||
var_subst subst(m());
|
||||
subst(_t, num_args, args, result);
|
||||
result = subst(_t, num_args, args);
|
||||
if (well_sorted_check_enabled() && !is_well_sorted(m(), result))
|
||||
throw cmd_exception("invalid macro application, sort mismatch ", s);
|
||||
return;
|
||||
|
@ -1625,6 +1625,7 @@ void cmd_context::display_dimacs() {
|
|||
void cmd_context::display_model(model_ref& mdl) {
|
||||
if (mdl) {
|
||||
if (m_mc0) (*m_mc0)(mdl);
|
||||
if (m_params.m_model_compress) mdl->compress();
|
||||
model_params p;
|
||||
if (p.v1() || p.v2()) {
|
||||
std::ostringstream buffer;
|
||||
|
|
|
@ -34,6 +34,7 @@ context_params::context_params() {
|
|||
m_debug_ref_count = false;
|
||||
m_smtlib2_compliant = false;
|
||||
m_well_sorted_check = false;
|
||||
m_model_compress = true;
|
||||
m_timeout = UINT_MAX;
|
||||
m_rlimit = 0;
|
||||
updt_params();
|
||||
|
@ -102,6 +103,9 @@ void context_params::set(char const * param, char const * value) {
|
|||
else if (p == "model_validate") {
|
||||
set_bool(m_model_validate, param, value);
|
||||
}
|
||||
else if (p == "model_compress") {
|
||||
set_bool(m_model_compress, param, value);
|
||||
}
|
||||
else if (p == "dump_models") {
|
||||
set_bool(m_dump_models, param, value);
|
||||
}
|
||||
|
@ -146,6 +150,7 @@ void context_params::updt_params(params_ref const & p) {
|
|||
m_proof = p.get_bool("proof", m_proof);
|
||||
m_model = p.get_bool("model", m_model);
|
||||
m_model_validate = p.get_bool("model_validate", m_model_validate);
|
||||
m_model_compress = p.get_bool("model_compress", m_model_compress);
|
||||
m_dump_models = p.get_bool("dump_models", m_dump_models);
|
||||
m_trace = p.get_bool("trace", m_trace);
|
||||
m_trace_file_name = p.get_str("trace_file_name", "z3.log");
|
||||
|
@ -162,6 +167,7 @@ void context_params::collect_param_descrs(param_descrs & d) {
|
|||
d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true");
|
||||
d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true");
|
||||
d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false");
|
||||
d.insert("model_compress", CPK_BOOL, "compress models for easier consumption", "true");
|
||||
d.insert("dump_models", CPK_BOOL, "dump models whenever check-sat returns sat", "false");
|
||||
d.insert("trace", CPK_BOOL, "trace generation for VCC", "false");
|
||||
d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log");
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
bool m_well_sorted_check;
|
||||
bool m_model;
|
||||
bool m_model_validate;
|
||||
bool m_model_compress;
|
||||
bool m_dump_models;
|
||||
bool m_unsat_core;
|
||||
bool m_smtlib2_compliant; // it must be here because it enable/disable the use of coercions in the ast_manager.
|
||||
|
|
|
@ -135,9 +135,8 @@ public:
|
|||
m_idx++;
|
||||
}
|
||||
void execute(cmd_context & ctx) override {
|
||||
expr_ref r(ctx.m());
|
||||
beta_reducer p(ctx.m());
|
||||
p(m_source, m_subst.size(), m_subst.c_ptr(), r);
|
||||
expr_ref r = p(m_source, m_subst.size(), m_subst.c_ptr());
|
||||
store_expr_ref(ctx, m_target, r.get());
|
||||
}
|
||||
};
|
||||
|
@ -274,8 +273,7 @@ UNARY_CMD(elim_unused_vars_cmd, "dbg-elim-unused-vars", "<expr>", "eliminate unu
|
|||
ctx.display(ctx.regular_stream(), arg);
|
||||
return;
|
||||
}
|
||||
expr_ref r(ctx.m());
|
||||
elim_unused_vars(ctx.m(), to_quantifier(arg), gparams::get_ref(), r);
|
||||
expr_ref r = elim_unused_vars(ctx.m(), to_quantifier(arg), gparams::get_ref());
|
||||
SASSERT(!is_quantifier(r) || !to_quantifier(r)->may_have_unused_vars());
|
||||
ctx.display(ctx.regular_stream(), r);
|
||||
ctx.regular_stream() << std::endl;
|
||||
|
@ -307,8 +305,7 @@ public:
|
|||
if (num != m_q->get_num_decls())
|
||||
throw cmd_exception("invalid command, mismatch between the number of quantified variables and the number of arguments.");
|
||||
unsigned i = num;
|
||||
while (i > 0) {
|
||||
--i;
|
||||
while (i-- > 0) {
|
||||
sort * s = ctx.m().get_sort(ts[i]);
|
||||
if (s != m_q->get_decl_sort(i)) {
|
||||
std::ostringstream buffer;
|
||||
|
@ -320,8 +317,7 @@ public:
|
|||
}
|
||||
|
||||
void execute(cmd_context & ctx) override {
|
||||
expr_ref r(ctx.m());
|
||||
instantiate(ctx.m(), m_q, m_args.c_ptr(), r);
|
||||
expr_ref r = instantiate(ctx.m(), m_q, m_args.c_ptr());
|
||||
ctx.display(ctx.regular_stream(), r);
|
||||
ctx.regular_stream() << std::endl;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,12 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "model/func_interp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "model/func_interp.h"
|
||||
|
||||
func_entry::func_entry(ast_manager & m, unsigned arity, expr * const * args, expr * result):
|
||||
m_args_are_values(true),
|
||||
|
@ -77,10 +78,7 @@ func_interp::func_interp(ast_manager & m, unsigned arity):
|
|||
}
|
||||
|
||||
func_interp::~func_interp() {
|
||||
ptr_vector<func_entry>::iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry* curr : m_entries) {
|
||||
curr->deallocate(m_manager, m_arity);
|
||||
}
|
||||
m_manager.dec_ref(m_else);
|
||||
|
@ -90,10 +88,7 @@ func_interp::~func_interp() {
|
|||
func_interp * func_interp::copy() const {
|
||||
func_interp * new_fi = alloc(func_interp, m_manager, m_arity);
|
||||
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry * curr : m_entries) {
|
||||
new_fi->insert_new_entry(curr->get_args(), curr->get_result());
|
||||
}
|
||||
new_fi->set_else(m_else);
|
||||
|
@ -141,9 +136,11 @@ void func_interp::set_else(expr * e) {
|
|||
return;
|
||||
|
||||
reset_interp_cache();
|
||||
|
||||
TRACE("func_interp", tout << "set_else: " << expr_ref(e, m()) << "\n";);
|
||||
|
||||
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;);
|
||||
insert_entry(args.c_ptr(), to_app(e)->get_arg(1));
|
||||
e = to_app(e)->get_arg(2);
|
||||
}
|
||||
|
@ -161,10 +158,7 @@ bool func_interp::is_constant() const {
|
|||
return false;
|
||||
if (!is_ground(m_else))
|
||||
return false;
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry* curr : m_entries) {
|
||||
if (curr->get_result() != m_else)
|
||||
return false;
|
||||
}
|
||||
|
@ -177,10 +171,7 @@ bool func_interp::is_constant() const {
|
|||
args_are_values to true if for all entries e e.args_are_values() is true.
|
||||
*/
|
||||
func_entry * func_interp::get_entry(expr * const * args) const {
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry* curr : m_entries) {
|
||||
if (curr->eq_args(m(), m_arity, args))
|
||||
return curr;
|
||||
}
|
||||
|
@ -224,7 +215,7 @@ bool func_interp::eval_else(expr * const * args, expr_ref & result) const {
|
|||
return false;
|
||||
var_subst s(m_manager, false);
|
||||
SASSERT(!s.std_order()); // (VAR 0) <- args[0], (VAR 1) <- args[1], ...
|
||||
s(m_else, m_arity, args, result);
|
||||
result = s(m_else, m_arity, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -237,10 +228,7 @@ expr * func_interp::get_max_occ_result() const {
|
|||
obj_map<expr, unsigned> num_occs;
|
||||
expr * r_max = nullptr;
|
||||
unsigned max = 0;
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry * curr : m_entries) {
|
||||
expr * r = curr->get_result();
|
||||
unsigned occs = 0;
|
||||
num_occs.find(r, occs);
|
||||
|
@ -262,15 +250,11 @@ void func_interp::compress() {
|
|||
return; // nothing to be done
|
||||
if (!is_ground(m_else))
|
||||
return; // forall entries e in m_entries e.get_result() is ground
|
||||
unsigned i = 0;
|
||||
unsigned j = 0;
|
||||
unsigned sz = m_entries.size();
|
||||
m_args_are_values = true;
|
||||
for (; i < sz; i++) {
|
||||
func_entry * curr = m_entries[i];
|
||||
for (func_entry * curr : m_entries) {
|
||||
if (curr->get_result() != m_else) {
|
||||
m_entries[j] = curr;
|
||||
j++;
|
||||
m_entries[j++] = curr;
|
||||
if (!curr->args_are_values())
|
||||
m_args_are_values = false;
|
||||
}
|
||||
|
@ -278,10 +262,58 @@ void func_interp::compress() {
|
|||
curr->deallocate(m_manager, m_arity);
|
||||
}
|
||||
}
|
||||
if (j < sz) {
|
||||
if (j < m_entries.size()) {
|
||||
reset_interp_cache();
|
||||
m_entries.shrink(j);
|
||||
}
|
||||
// other compression, if else is a default branch.
|
||||
// or function encode identity.
|
||||
if (m_manager.is_false(m_else)) {
|
||||
expr_ref new_else(get_interp(), m_manager);
|
||||
for (func_entry * curr : m_entries) {
|
||||
curr->deallocate(m_manager, m_arity);
|
||||
}
|
||||
m_entries.reset();
|
||||
reset_interp_cache();
|
||||
m_manager.inc_ref(new_else);
|
||||
m_manager.dec_ref(m_else);
|
||||
m_else = new_else;
|
||||
}
|
||||
else if (!m_entries.empty() && is_identity()) {
|
||||
for (func_entry * curr : m_entries) {
|
||||
curr->deallocate(m_manager, m_arity);
|
||||
}
|
||||
m_entries.reset();
|
||||
reset_interp_cache();
|
||||
expr_ref new_else(m_manager.mk_var(0, m_manager.get_sort(m_else)), m_manager);
|
||||
m_manager.inc_ref(new_else);
|
||||
m_manager.dec_ref(m_else);
|
||||
m_else = new_else;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief check if function is identity
|
||||
*/
|
||||
bool func_interp::is_identity() const {
|
||||
if (m_arity != 1) return false;
|
||||
if (m_else == nullptr) return false;
|
||||
|
||||
// all entries map a value to itself
|
||||
for (func_entry * curr : m_entries) {
|
||||
if (curr->get_arg(0) != curr->get_result()) return false;
|
||||
if (curr->get_result() == m_else) return false;
|
||||
}
|
||||
if (is_var(m_else)) return true;
|
||||
if (!m_manager.is_value(m_else)) return false;
|
||||
sort_size const& sz = m_manager.get_sort(m_else)->get_num_elements();
|
||||
if (!sz.is_finite()) return false;
|
||||
|
||||
//
|
||||
// the else entry is a value not covered by other entries
|
||||
// it, together with the entries covers the entire domain.
|
||||
//
|
||||
return (sz.size() == m_entries.size() + 1);
|
||||
}
|
||||
|
||||
expr * func_interp::get_interp_core() const {
|
||||
|
@ -289,10 +321,10 @@ expr * func_interp::get_interp_core() const {
|
|||
return nullptr;
|
||||
expr * r = m_else;
|
||||
ptr_buffer<expr> vars;
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry * curr : m_entries) {
|
||||
if (m_else == curr->get_result()) {
|
||||
continue;
|
||||
}
|
||||
if (vars.empty()) {
|
||||
for (unsigned i = 0; i < m_arity; i++) {
|
||||
vars.push_back(m_manager.mk_var(i, m_manager.get_sort(curr->get_arg(i))));
|
||||
|
@ -303,12 +335,17 @@ expr * func_interp::get_interp_core() const {
|
|||
eqs.push_back(m_manager.mk_eq(vars[i], curr->get_arg(i)));
|
||||
}
|
||||
SASSERT(eqs.size() == m_arity);
|
||||
expr * cond;
|
||||
if (m_arity == 1)
|
||||
cond = eqs.get(0);
|
||||
else
|
||||
cond = m_manager.mk_and(eqs.size(), eqs.c_ptr());
|
||||
r = m_manager.mk_ite(cond, curr->get_result(), r);
|
||||
expr * cond = mk_and(m_manager, eqs.size(), eqs.c_ptr());
|
||||
expr * th = curr->get_result();
|
||||
if (m_manager.is_true(th)) {
|
||||
r = m_manager.mk_or(cond, r);
|
||||
}
|
||||
else if (m_manager.is_false(th)) {
|
||||
r = m_manager.mk_and(m_manager.mk_not(cond), r);
|
||||
}
|
||||
else {
|
||||
r = m_manager.mk_ite(cond, th, r);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -327,12 +364,9 @@ expr * func_interp::get_interp() const {
|
|||
func_interp * func_interp::translate(ast_translation & translator) const {
|
||||
func_interp * new_fi = alloc(func_interp, translator.to(), m_arity);
|
||||
|
||||
ptr_vector<func_entry>::const_iterator it = m_entries.begin();
|
||||
ptr_vector<func_entry>::const_iterator end = m_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
func_entry * curr = *it;
|
||||
for (func_entry * curr : m_entries) {
|
||||
ptr_buffer<expr> new_args;
|
||||
for (unsigned i=0; i<m_arity; i++)
|
||||
for (unsigned i = 0; i < m_arity; i++)
|
||||
new_args.push_back(translator(curr->get_arg(i)));
|
||||
new_fi->insert_new_entry(new_args.c_ptr(), translator(curr->get_result()));
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
expr * get_result() const { return m_result; }
|
||||
expr * get_arg(unsigned idx) const { return m_args[idx]; }
|
||||
expr * const * get_args() const { return m_args; }
|
||||
|
||||
/**
|
||||
\brief Return true if m.are_equal(m_args[i], args[i]) for all i in [0, arity)
|
||||
*/
|
||||
|
@ -101,6 +102,8 @@ public:
|
|||
func_entry * get_entry(expr * const * args) const;
|
||||
bool eval_else(expr * const * args, expr_ref & result) const;
|
||||
unsigned num_entries() const { return m_entries.size(); }
|
||||
ptr_vector<func_entry>::const_iterator begin() const { return m_entries.begin(); }
|
||||
ptr_vector<func_entry>::const_iterator end() const { return m_entries.end(); }
|
||||
func_entry const * const * get_entries() const { return m_entries.c_ptr(); }
|
||||
func_entry const * get_entry(unsigned idx) const { return m_entries[idx]; }
|
||||
|
||||
|
@ -113,6 +116,7 @@ public:
|
|||
|
||||
private:
|
||||
bool is_fi_entry_expr(expr * e, ptr_vector<expr> & args);
|
||||
bool is_identity() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,34 +16,36 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "model/model.h"
|
||||
#include "util/top_sort.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/used_symbols.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/for_each_ast.h"
|
||||
#include "model/model.h"
|
||||
#include "model/model_evaluator.h"
|
||||
|
||||
model::model(ast_manager & m):
|
||||
model_core(m),
|
||||
m_mev(*this) {
|
||||
m_mev(*this),
|
||||
m_cleaned(false) {
|
||||
}
|
||||
|
||||
model::~model() {
|
||||
for (auto & kv : m_usort2universe) {
|
||||
m_manager.dec_ref(kv.m_key);
|
||||
m_manager.dec_array_ref(kv.m_value->size(), kv.m_value->c_ptr());
|
||||
m.dec_ref(kv.m_key);
|
||||
m.dec_array_ref(kv.m_value->size(), kv.m_value->c_ptr());
|
||||
dealloc(kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void model::copy_const_interps(model const & source) {
|
||||
for (auto const& kv : source.m_interp) {
|
||||
for (auto const& kv : source.m_interp)
|
||||
register_decl(kv.m_key, kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void model::copy_func_interps(model const & source) {
|
||||
|
@ -57,13 +59,11 @@ void model::copy_usort_interps(model const & source) {
|
|||
}
|
||||
|
||||
model * model::copy() const {
|
||||
model * m = alloc(model, m_manager);
|
||||
|
||||
m->copy_const_interps(*this);
|
||||
m->copy_func_interps(*this);
|
||||
m->copy_usort_interps(*this);
|
||||
|
||||
return m;
|
||||
model * mdl = alloc(model, m);
|
||||
mdl->copy_const_interps(*this);
|
||||
mdl->copy_func_interps(*this);
|
||||
mdl->copy_usort_interps(*this);
|
||||
return mdl;
|
||||
}
|
||||
|
||||
bool model::eval_expr(expr * e, expr_ref & result, bool model_completion) {
|
||||
|
@ -94,13 +94,13 @@ struct model::value_proc : public some_value_proc {
|
|||
|
||||
expr * model::get_some_value(sort * s) {
|
||||
value_proc p(*this);
|
||||
return m_manager.get_some_value(s, &p);
|
||||
return m.get_some_value(s, &p);
|
||||
}
|
||||
|
||||
ptr_vector<expr> const & model::get_universe(sort * s) const {
|
||||
ptr_vector<expr> * u = nullptr;
|
||||
m_usort2universe.find(s, u);
|
||||
SASSERT(u != 0);
|
||||
SASSERT(u != nullptr);
|
||||
return *u;
|
||||
}
|
||||
|
||||
|
@ -120,11 +120,11 @@ sort * model::get_uninterpreted_sort(unsigned idx) const {
|
|||
|
||||
void model::register_usort(sort * s, unsigned usize, expr * const * universe) {
|
||||
sort2universe::obj_map_entry * entry = m_usort2universe.insert_if_not_there2(s, 0);
|
||||
m_manager.inc_array_ref(usize, universe);
|
||||
m.inc_array_ref(usize, universe);
|
||||
if (entry->get_data().m_value == 0) {
|
||||
// new entry
|
||||
m_usorts.push_back(s);
|
||||
m_manager.inc_ref(s);
|
||||
m.inc_ref(s);
|
||||
ptr_vector<expr> * new_u = alloc(ptr_vector<expr>);
|
||||
new_u->append(usize, universe);
|
||||
entry->get_data().m_value = new_u;
|
||||
|
@ -133,7 +133,7 @@ void model::register_usort(sort * s, unsigned usize, expr * const * universe) {
|
|||
// updating
|
||||
ptr_vector<expr> * u = entry->get_data().m_value;
|
||||
SASSERT(u);
|
||||
m_manager.dec_array_ref(u->size(), u->c_ptr());
|
||||
m.dec_array_ref(u->size(), u->c_ptr());
|
||||
u->append(usize, universe);
|
||||
}
|
||||
}
|
||||
|
@ -154,8 +154,8 @@ model * model::translate(ast_translation & translator) const {
|
|||
// Translate usort interps
|
||||
for (auto const& kv : m_usort2universe) {
|
||||
ptr_vector<expr> new_universe;
|
||||
for (unsigned i=0; i < kv.m_value->size(); i++)
|
||||
new_universe.push_back(translator(kv.m_value->get(i)));
|
||||
for (expr* e : *kv.m_value)
|
||||
new_universe.push_back(translator(e));
|
||||
res->register_usort(translator(kv.m_key),
|
||||
new_universe.size(),
|
||||
new_universe.c_ptr());
|
||||
|
@ -164,22 +164,322 @@ model * model::translate(ast_translation & translator) const {
|
|||
return res;
|
||||
}
|
||||
|
||||
struct model::top_sort : public ::top_sort<func_decl> {
|
||||
th_rewriter m_rewrite;
|
||||
obj_map<func_decl, unsigned> m_occur_count;
|
||||
|
||||
top_sort(ast_manager& m):
|
||||
m_rewrite(m)
|
||||
{}
|
||||
|
||||
void add_occurs(func_decl* f) {
|
||||
m_occur_count.insert(f, occur_count(f) + 1);
|
||||
}
|
||||
|
||||
unsigned occur_count(func_decl* f) const {
|
||||
unsigned count = 0;
|
||||
m_occur_count.find(f, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
~top_sort() override {}
|
||||
};
|
||||
|
||||
void model::compress() {
|
||||
if (m_cleaned) return;
|
||||
|
||||
// stratify m_finterp and m_decls in a topological sort
|
||||
// such that functions f1 < f2 then f1 does not use f2.
|
||||
// then for each function in order clean-up the interpretations
|
||||
// by substituting in auxiliary definitions that can be eliminated.
|
||||
|
||||
func_decl_ref_vector pinned(m);
|
||||
while (true) {
|
||||
top_sort ts(m);
|
||||
collect_deps(ts);
|
||||
ts.topological_sort();
|
||||
for (func_decl * f : ts.top_sorted()) {
|
||||
cleanup_interp(ts, f);
|
||||
}
|
||||
|
||||
func_decl_set removed;
|
||||
ts.m_occur_count.reset();
|
||||
for (func_decl * f : ts.top_sorted()) {
|
||||
collect_occs(ts, f);
|
||||
}
|
||||
|
||||
// remove auxiliary declarations that are not used.
|
||||
for (func_decl * f : ts.top_sorted()) {
|
||||
if (f->is_skolem() && ts.occur_count(f) == 0) {
|
||||
pinned.push_back(f);
|
||||
unregister_decl(f);
|
||||
removed.insert(f);
|
||||
}
|
||||
}
|
||||
if (removed.empty()) break;
|
||||
remove_decls(m_decls, removed);
|
||||
remove_decls(m_func_decls, removed);
|
||||
remove_decls(m_const_decls, removed);
|
||||
}
|
||||
m_cleaned = true;
|
||||
reset_eval_cache();
|
||||
}
|
||||
|
||||
|
||||
void model::collect_deps(top_sort& ts) {
|
||||
for (auto const& kv : m_finterp) {
|
||||
ts.insert(kv.m_key, collect_deps(ts, kv.m_value));
|
||||
}
|
||||
for (auto const& kv : m_interp) {
|
||||
ts.insert(kv.m_key, collect_deps(ts, kv.m_value));
|
||||
}
|
||||
}
|
||||
|
||||
struct model::deps_collector {
|
||||
model& m;
|
||||
top_sort& ts;
|
||||
func_decl_set& s;
|
||||
array_util autil;
|
||||
deps_collector(model& m, top_sort& ts, func_decl_set& s): m(m), ts(ts), s(s), autil(m.get_manager()) {}
|
||||
void operator()(app* a) {
|
||||
func_decl* f = a->get_decl();
|
||||
if (autil.is_as_array(f)) {
|
||||
f = autil.get_as_array_func_decl(a);
|
||||
}
|
||||
if (m.has_interpretation(f)) {
|
||||
s.insert(f);
|
||||
ts.add_occurs(f);
|
||||
}
|
||||
}
|
||||
void operator()(expr* ) {}
|
||||
};
|
||||
|
||||
struct model::occs_collector {
|
||||
top_sort& ts;
|
||||
occs_collector(top_sort& ts): ts(ts) {}
|
||||
void operator()(func_decl* f) {
|
||||
ts.add_occurs(f);
|
||||
}
|
||||
void operator()(ast* ) {}
|
||||
};
|
||||
|
||||
|
||||
model::func_decl_set* model::collect_deps(top_sort& ts, expr * e) {
|
||||
func_decl_set* s = alloc(func_decl_set);
|
||||
deps_collector collector(*this, ts, *s);
|
||||
if (e) for_each_expr(collector, e);
|
||||
return s;
|
||||
}
|
||||
|
||||
model::func_decl_set* model::collect_deps(top_sort& ts, func_interp * fi) {
|
||||
func_decl_set* s = alloc(func_decl_set);
|
||||
deps_collector collector(*this, ts, *s);
|
||||
fi->compress();
|
||||
expr* e = fi->get_else();
|
||||
if (e) for_each_expr(collector, e);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Inline interpretations of skolem functions
|
||||
*/
|
||||
|
||||
void model::cleanup_interp(top_sort& ts, func_decl* f) {
|
||||
unsigned pid = ts.partition_id(f);
|
||||
expr * e1 = get_const_interp(f);
|
||||
if (e1) {
|
||||
expr_ref e2 = cleanup_expr(ts, e1, pid);
|
||||
if (e2 != e1)
|
||||
register_decl(f, e2);
|
||||
return;
|
||||
}
|
||||
func_interp* fi = get_func_interp(f);
|
||||
if (fi) {
|
||||
e1 = fi->get_else();
|
||||
expr_ref e2 = cleanup_expr(ts, e1, pid);
|
||||
if (e1 != e2)
|
||||
fi->set_else(e2);
|
||||
}
|
||||
}
|
||||
|
||||
void model::collect_occs(top_sort& ts, func_decl* f) {
|
||||
expr * e = get_const_interp(f);
|
||||
if (e) {
|
||||
collect_occs(ts, e);
|
||||
}
|
||||
else {
|
||||
func_interp* fi = get_func_interp(f);
|
||||
if (fi) {
|
||||
e = fi->get_else();
|
||||
collect_occs(ts, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void model::collect_occs(top_sort& ts, expr* e) {
|
||||
occs_collector collector(ts);
|
||||
for_each_ast(collector, e);
|
||||
}
|
||||
|
||||
bool model::can_inline_def(top_sort& ts, func_decl* f) {
|
||||
if (ts.occur_count(f) <= 1) return true;
|
||||
func_interp* fi = get_func_interp(f);
|
||||
if (!fi) return false;
|
||||
if (fi->get_else() == nullptr) return false;
|
||||
expr* e = fi->get_else();
|
||||
obj_hashtable<expr> subs;
|
||||
ptr_buffer<expr> todo;
|
||||
todo.push_back(e);
|
||||
while (!todo.empty()) {
|
||||
if (fi->num_entries() + subs.size() > 8) return false;
|
||||
expr* e = todo.back();
|
||||
todo.pop_back();
|
||||
if (subs.contains(e)) continue;
|
||||
subs.insert(e);
|
||||
if (is_app(e)) {
|
||||
for (expr* arg : *to_app(e)) {
|
||||
todo.push_back(arg);
|
||||
}
|
||||
}
|
||||
else if (is_quantifier(e)) {
|
||||
todo.push_back(to_quantifier(e)->get_expr());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition) {
|
||||
if (!e) return expr_ref(0, m);
|
||||
|
||||
TRACE("model", tout << "cleaning up:\n" << mk_pp(e, m) << "\n";);
|
||||
|
||||
obj_map<expr, expr*> cache;
|
||||
expr_ref_vector trail(m);
|
||||
ptr_buffer<expr, 128> todo;
|
||||
ptr_buffer<expr> args;
|
||||
todo.push_back(e);
|
||||
array_util autil(m);
|
||||
func_interp* fi = nullptr;
|
||||
unsigned pid = 0;
|
||||
expr_ref new_t(m);
|
||||
|
||||
while (!todo.empty()) {
|
||||
expr* a = todo.back();
|
||||
switch(a->get_kind()) {
|
||||
case AST_APP: {
|
||||
app * t = to_app(a);
|
||||
func_decl* f = t->get_decl();
|
||||
bool visited = true;
|
||||
|
||||
args.reset();
|
||||
for (expr* t_arg : *t) {
|
||||
expr * arg = nullptr;
|
||||
if (!cache.find(t_arg, arg)) {
|
||||
visited = false;
|
||||
todo.push_back(t_arg);
|
||||
}
|
||||
else {
|
||||
args.push_back(arg);
|
||||
}
|
||||
}
|
||||
if (!visited) {
|
||||
continue;
|
||||
}
|
||||
fi = nullptr;
|
||||
if (autil.is_as_array(a)) {
|
||||
func_decl* f = autil.get_as_array_func_decl(a);
|
||||
// only expand auxiliary definitions that occur once.
|
||||
if (can_inline_def(ts, f)) {
|
||||
fi = get_func_interp(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (fi && fi->get_interp()) {
|
||||
f = autil.get_as_array_func_decl(a);
|
||||
expr_ref_vector sargs(m);
|
||||
sort_ref_vector vars(m);
|
||||
svector<symbol> var_names;
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
||||
var_names.push_back(symbol(i));
|
||||
vars.push_back(f->get_domain(f->get_arity() - i - 1));
|
||||
}
|
||||
new_t = m.mk_lambda(vars.size(), vars.c_ptr(), var_names.c_ptr(), fi->get_interp());
|
||||
}
|
||||
else if (f->is_skolem() && can_inline_def(ts, f) && (fi = get_func_interp(f)) &&
|
||||
fi->get_interp() && (!ts.partition_ids().find(f, pid) || pid != current_partition)) {
|
||||
var_subst vs(m);
|
||||
// ? TBD args.reverse();
|
||||
new_t = vs(fi->get_interp(), args.size(), args.c_ptr());
|
||||
}
|
||||
#if 0
|
||||
else if (is_uninterp_const(a) && !get_const_interp(f)) {
|
||||
new_t = get_some_value(f->get_range());
|
||||
register_decl(f, new_t);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
new_t = ts.m_rewrite.mk_app(f, args.size(), args.c_ptr());
|
||||
}
|
||||
|
||||
if (t != new_t.get()) trail.push_back(new_t);
|
||||
todo.pop_back();
|
||||
cache.insert(t, new_t);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SASSERT(a != nullptr);
|
||||
cache.insert(a, a);
|
||||
todo.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ts.m_rewrite(cache[e], new_t);
|
||||
return new_t;
|
||||
}
|
||||
|
||||
void model::remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s) {
|
||||
unsigned j = 0;
|
||||
for (func_decl* f : decls) {
|
||||
if (!s.contains(f)) {
|
||||
decls[j++] = f;
|
||||
}
|
||||
}
|
||||
decls.shrink(j);
|
||||
}
|
||||
|
||||
|
||||
expr_ref model::get_inlined_const_interp(func_decl* f) {
|
||||
expr* v = get_const_interp(f);
|
||||
if (!v) return expr_ref(0, m);
|
||||
top_sort st(m);
|
||||
expr_ref result1(v, m);
|
||||
expr_ref result2 = cleanup_expr(st, v, UINT_MAX);
|
||||
while (result1 != result2) {
|
||||
result1 = result2;
|
||||
result2 = cleanup_expr(st, result1, UINT_MAX);
|
||||
}
|
||||
return result2;
|
||||
}
|
||||
|
||||
expr_ref model::operator()(expr* t) {
|
||||
return m_mev(t);
|
||||
}
|
||||
|
||||
expr_ref_vector model::operator()(expr_ref_vector const& ts) {
|
||||
expr_ref_vector rs(m());
|
||||
expr_ref_vector rs(m);
|
||||
for (expr* t : ts) rs.push_back((*this)(t));
|
||||
return rs;
|
||||
}
|
||||
|
||||
bool model::is_true(expr* t) {
|
||||
return m().is_true((*this)(t));
|
||||
return m.is_true((*this)(t));
|
||||
}
|
||||
|
||||
bool model::is_false(expr* t) {
|
||||
return m().is_false((*this)(t));
|
||||
return m.is_false((*this)(t));
|
||||
}
|
||||
|
||||
bool model::is_true(expr_ref_vector const& ts) {
|
||||
|
|
|
@ -30,12 +30,28 @@ typedef ref<model> model_ref;
|
|||
class model : public model_core {
|
||||
protected:
|
||||
typedef obj_map<sort, ptr_vector<expr>*> sort2universe;
|
||||
typedef obj_hashtable<func_decl> func_decl_set;
|
||||
|
||||
ptr_vector<sort> m_usorts;
|
||||
sort2universe m_usort2universe;
|
||||
model_evaluator m_mev;
|
||||
bool m_cleaned;
|
||||
struct value_proc;
|
||||
|
||||
struct deps_collector;
|
||||
struct occs_collector;
|
||||
struct top_sort;
|
||||
|
||||
func_decl_set* collect_deps(top_sort& ts, expr * e);
|
||||
func_decl_set* collect_deps(top_sort& ts, func_interp* fi);
|
||||
void collect_deps(top_sort& ts);
|
||||
void collect_occs(top_sort& ts, func_decl* f);
|
||||
void collect_occs(top_sort& ts, expr* e);
|
||||
void cleanup_interp(top_sort& ts, func_decl * f);
|
||||
expr_ref cleanup_expr(top_sort& ts, expr* e, unsigned current_partition);
|
||||
void remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s);
|
||||
bool can_inline_def(top_sort& ts, func_decl* f);
|
||||
|
||||
public:
|
||||
model(ast_manager & m);
|
||||
~model() override;
|
||||
|
@ -54,6 +70,8 @@ public:
|
|||
sort * get_uninterpreted_sort(unsigned idx) const override;
|
||||
bool has_uninterpreted_sort(sort * s) const;
|
||||
|
||||
expr_ref get_inlined_const_interp(func_decl* f);
|
||||
|
||||
//
|
||||
// Primitives for building models
|
||||
//
|
||||
|
@ -63,6 +81,8 @@ public:
|
|||
//
|
||||
model * translate(ast_translation & translator) const;
|
||||
|
||||
void compress();
|
||||
|
||||
void set_model_completion(bool f) { m_mev.set_model_completion(f); }
|
||||
void updt_params(params_ref const & p) { m_mev.updt_params(p); }
|
||||
|
||||
|
@ -94,7 +114,5 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, model_core const& m);
|
||||
|
||||
|
||||
#endif /* MODEL_H_ */
|
||||
|
|
|
@ -147,7 +147,7 @@ void model2expr(model& md, expr_ref& result) {
|
|||
}
|
||||
if (f->get_arity() > 0) {
|
||||
var_subst vs(m, false);
|
||||
vs(tmp, rev_vars.size(), rev_vars.c_ptr(), tmp);
|
||||
tmp = vs(tmp, rev_vars.size(), rev_vars.c_ptr());
|
||||
tmp = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp);
|
||||
}
|
||||
conjs.push_back(tmp);
|
||||
|
|
|
@ -20,12 +20,12 @@ Revision History:
|
|||
|
||||
model_core::~model_core() {
|
||||
for (auto & kv : m_interp) {
|
||||
m_manager.dec_ref(kv.m_key);
|
||||
m_manager.dec_ref(kv.m_value);
|
||||
m.dec_ref(kv.m_key);
|
||||
m.dec_ref(kv.m_value);
|
||||
}
|
||||
|
||||
for (auto & kv : m_finterp) {
|
||||
m_manager.dec_ref(kv.m_key);
|
||||
m.dec_ref(kv.m_key);
|
||||
dealloc(kv.m_value);
|
||||
}
|
||||
}
|
||||
|
@ -47,32 +47,33 @@ bool model_core::eval(func_decl* f, expr_ref & r) const {
|
|||
|
||||
void model_core::register_decl(func_decl * d, expr * v) {
|
||||
SASSERT(d->get_arity() == 0);
|
||||
TRACE("model", tout << "register " << d->get_name() << "\n";);
|
||||
decl2expr::obj_map_entry * entry = m_interp.insert_if_not_there2(d, nullptr);
|
||||
if (entry->get_data().m_value == nullptr) {
|
||||
// new entry
|
||||
m_decls.push_back(d);
|
||||
m_const_decls.push_back(d);
|
||||
m_manager.inc_ref(d);
|
||||
m_manager.inc_ref(v);
|
||||
m.inc_ref(d);
|
||||
m.inc_ref(v);
|
||||
entry->get_data().m_value = v;
|
||||
}
|
||||
else {
|
||||
// replacing entry
|
||||
m_manager.inc_ref(v);
|
||||
m_manager.dec_ref(entry->get_data().m_value);
|
||||
m.inc_ref(v);
|
||||
m.dec_ref(entry->get_data().m_value);
|
||||
entry->get_data().m_value = v;
|
||||
}
|
||||
}
|
||||
|
||||
void model_core::register_decl(func_decl * d, func_interp * fi) {
|
||||
SASSERT(d->get_arity() > 0);
|
||||
SASSERT(&fi->m() == &m_manager);
|
||||
SASSERT(&fi->m() == &m);
|
||||
decl2finterp::obj_map_entry * entry = m_finterp.insert_if_not_there2(d, nullptr);
|
||||
if (entry->get_data().m_value == nullptr) {
|
||||
// new entry
|
||||
m_decls.push_back(d);
|
||||
m_func_decls.push_back(d);
|
||||
m_manager.inc_ref(d);
|
||||
m.inc_ref(d);
|
||||
entry->get_data().m_value = fi;
|
||||
}
|
||||
else {
|
||||
|
@ -85,23 +86,23 @@ 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) {
|
||||
if (ec) {
|
||||
auto k = ec->get_data().m_key;
|
||||
auto v = ec->get_data().m_value;
|
||||
m_interp.remove(d);
|
||||
m_const_decls.erase(d);
|
||||
m_manager.dec_ref(k);
|
||||
m_manager.dec_ref(v);
|
||||
m.dec_ref(k);
|
||||
m.dec_ref(v);
|
||||
return;
|
||||
}
|
||||
|
||||
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
|
||||
if (ef && ef->get_data().m_value != 0) {
|
||||
if (ef) {
|
||||
auto k = ef->get_data().m_key;
|
||||
auto v = ef->get_data().m_value;
|
||||
m_finterp.remove(d);
|
||||
m_func_decls.erase(d);
|
||||
m_manager.dec_ref(k);
|
||||
m.dec_ref(k);
|
||||
dealloc(v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class model_core {
|
|||
protected:
|
||||
typedef obj_map<func_decl, expr *> decl2expr;
|
||||
typedef obj_map<func_decl, func_interp*> decl2finterp;
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
unsigned m_ref_count;
|
||||
decl2expr m_interp; //!< interpretation for uninterpreted constants
|
||||
decl2finterp m_finterp; //!< interpretation for uninterpreted functions
|
||||
|
@ -36,11 +36,10 @@ protected:
|
|||
ptr_vector<func_decl> m_func_decls;
|
||||
|
||||
public:
|
||||
model_core(ast_manager & m):m_manager(m), m_ref_count(0) { }
|
||||
model_core(ast_manager & m):m(m), m_ref_count(0) { }
|
||||
virtual ~model_core();
|
||||
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
ast_manager& m() const { return m_manager; }
|
||||
ast_manager & get_manager() const { return m; }
|
||||
|
||||
unsigned get_num_decls() const { return m_decls.size(); }
|
||||
func_decl * get_decl(unsigned i) const { return m_decls[i]; }
|
||||
|
@ -65,6 +64,11 @@ public:
|
|||
|
||||
virtual expr * get_some_value(sort * s) = 0;
|
||||
|
||||
expr * get_some_const_interp(func_decl * d) {
|
||||
expr * r = get_const_interp(d);
|
||||
if (r) return r;
|
||||
return get_some_value(d->get_range());
|
||||
}
|
||||
//
|
||||
// Reference counting
|
||||
//
|
||||
|
@ -78,4 +82,7 @@ public:
|
|||
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, model_core const& m);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,10 +16,12 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "util/cooperate.h"
|
||||
#include "model/model.h"
|
||||
#include "model/model_evaluator_params.hpp"
|
||||
#include "ast/rewriter/rewriter_types.h"
|
||||
#include "model/model_evaluator.h"
|
||||
#include "model/model_v2_pp.h"
|
||||
#include "ast/rewriter/rewriter_types.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "ast/rewriter/arith_rewriter.h"
|
||||
#include "ast/rewriter/bv_rewriter.h"
|
||||
|
@ -29,7 +31,6 @@ Revision History:
|
|||
#include "ast/rewriter/array_rewriter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "model/model_smt2_pp.h"
|
||||
|
@ -274,7 +275,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
fi->set_else(m.get_some_value(f->get_range()));
|
||||
|
||||
var_subst vs(m, false);
|
||||
vs(fi->get_interp(), num, args, result);
|
||||
result = vs(fi->get_interp(), num, args);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,6 +304,6 @@ void model_smt2_pp(std::ostream & out, ast_manager & m, model_core const & md, u
|
|||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, model_core const& m) {
|
||||
model_smt2_pp(out, m.m(), m, 0);
|
||||
model_smt2_pp(out, m.get_manager(), m, 0);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ expr_ref bind_variables::operator()(expr* fml, bool is_forall) {
|
|||
if (!m_names.empty()) {
|
||||
m_bound.reverse();
|
||||
m_names.reverse();
|
||||
result = m.mk_quantifier(is_forall, m_bound.size(), m_bound.c_ptr(), m_names.c_ptr(), result);
|
||||
result = m.mk_quantifier(is_forall ? forall_k : exists_k, m_bound.size(), m_bound.c_ptr(), m_names.c_ptr(), result);
|
||||
}
|
||||
m_pinned.reset();
|
||||
m_cache.reset();
|
||||
|
|
|
@ -1044,7 +1044,7 @@ namespace datalog {
|
|||
quantifier* q = to_quantifier(body);
|
||||
expr* e = q->get_expr();
|
||||
if (m.is_implies(e, body, e2)) {
|
||||
fml = m.mk_quantifier(false, q->get_num_decls(),
|
||||
fml = m.mk_quantifier(exists_k, q->get_num_decls(),
|
||||
q->get_decl_sorts(), q->get_decl_names(),
|
||||
body);
|
||||
}
|
||||
|
@ -1251,13 +1251,10 @@ namespace datalog {
|
|||
obj_map<sort, unsigned> max_vars;
|
||||
for (unsigned i = 0; i < rules.size(); ++i) {
|
||||
expr* r = rules[i].get();
|
||||
if (!is_quantifier(r)) {
|
||||
if (!is_forall(r)) {
|
||||
continue;
|
||||
}
|
||||
quantifier* q = to_quantifier(r);
|
||||
if (!q->is_forall()) {
|
||||
continue;
|
||||
}
|
||||
if (has_quantifiers(q->get_expr())) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1292,7 +1289,7 @@ namespace datalog {
|
|||
subst.push_back(fresh_vars[vars[max_var]].get());
|
||||
}
|
||||
|
||||
vsubst(q->get_expr(), subst.size(), subst.c_ptr(), res);
|
||||
res = vsubst(q->get_expr(), subst.size(), subst.c_ptr());
|
||||
rules[i] = res.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -292,7 +292,7 @@ namespace datalog {
|
|||
args.push_back(m.mk_var(0, m.mk_bool_sort()));
|
||||
}
|
||||
}
|
||||
sub(q, args.size(), args.c_ptr(), q);
|
||||
q = sub(q, args.size(), args.c_ptr());
|
||||
vars.reset();
|
||||
m_free_vars(q);
|
||||
vars.append(m_free_vars.size(), m_free_vars.c_ptr());
|
||||
|
@ -438,11 +438,7 @@ namespace datalog {
|
|||
e = e2;
|
||||
}
|
||||
}
|
||||
if (is_quantifier(e)) {
|
||||
q = to_quantifier(e);
|
||||
return q->is_forall();
|
||||
}
|
||||
return false;
|
||||
return ::is_forall(e);
|
||||
}
|
||||
|
||||
|
||||
|
@ -745,7 +741,7 @@ namespace datalog {
|
|||
expr_ref unbound_tail_pre_quant(m), fixed_tail(m), quant_tail(m);
|
||||
|
||||
var_subst vs(m, false);
|
||||
vs(unbound_tail, subst.size(), subst.c_ptr(), unbound_tail_pre_quant);
|
||||
unbound_tail_pre_quant = vs(unbound_tail, subst.size(), subst.c_ptr());
|
||||
|
||||
quant_tail = m.mk_exists(q_var_cnt, qsorts.c_ptr(), qnames.c_ptr(), unbound_tail_pre_quant);
|
||||
|
||||
|
@ -816,10 +812,10 @@ namespace datalog {
|
|||
app_ref_vector new_tail(m);
|
||||
svector<bool> tail_neg;
|
||||
var_subst vs(m, false);
|
||||
vs(r->get_head(), sz, es, tmp);
|
||||
tmp = vs(r->get_head(), sz, es);
|
||||
new_head = to_app(tmp);
|
||||
for (unsigned i = 0; i < r->get_tail_size(); ++i) {
|
||||
vs(r->get_tail(i), sz, es, tmp);
|
||||
tmp = vs(r->get_tail(i), sz, es);
|
||||
new_tail.push_back(to_app(tmp));
|
||||
tail_neg.push_back(r->is_neg_tail(i));
|
||||
}
|
||||
|
@ -984,8 +980,7 @@ namespace datalog {
|
|||
|
||||
var_subst vs(m, false);
|
||||
|
||||
expr_ref new_head_e(m);
|
||||
vs(m_head, subst_vals.size(), subst_vals.c_ptr(), new_head_e);
|
||||
expr_ref new_head_e = vs(m_head, subst_vals.size(), subst_vals.c_ptr());
|
||||
|
||||
m.inc_ref(new_head_e);
|
||||
m.dec_ref(m_head);
|
||||
|
@ -993,8 +988,7 @@ namespace datalog {
|
|||
|
||||
for (unsigned i = 0; i < m_tail_size; i++) {
|
||||
app * old_tail = get_tail(i);
|
||||
expr_ref new_tail_e(m);
|
||||
vs(old_tail, subst_vals.size(), subst_vals.c_ptr(), new_tail_e);
|
||||
expr_ref new_tail_e = vs(old_tail, subst_vals.size(), subst_vals.c_ptr());
|
||||
bool sign = is_neg_tail(i);
|
||||
m.inc_ref(new_tail_e);
|
||||
m.dec_ref(old_tail);
|
||||
|
|
|
@ -82,12 +82,10 @@ namespace datalog {
|
|||
quantifier_finder_proc() : m_exist(false), m_univ(false) {}
|
||||
void operator()(var * n) { }
|
||||
void operator()(quantifier * n) {
|
||||
if (n->is_forall()) {
|
||||
m_univ = true;
|
||||
}
|
||||
else {
|
||||
SASSERT(n->is_exists());
|
||||
m_exist = true;
|
||||
switch (n->get_kind()) {
|
||||
case forall_k: m_univ = true; break;
|
||||
case exists_k: m_exist = true; break;
|
||||
case lambda_k: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
void operator()(app * n) { }
|
||||
|
|
|
@ -31,27 +31,20 @@ namespace datalog {
|
|||
rule_dependencies::rule_dependencies(const rule_dependencies & o, bool reversed):
|
||||
m_context(o.m_context) {
|
||||
if (reversed) {
|
||||
iterator oit = o.begin();
|
||||
iterator oend = o.end();
|
||||
for (; oit!=oend; ++oit) {
|
||||
func_decl * pred = oit->m_key;
|
||||
item_set & orig_items = *oit->get_value();
|
||||
for (auto & kv : o) {
|
||||
func_decl * pred = kv.m_key;
|
||||
item_set & orig_items = *kv.get_value();
|
||||
|
||||
ensure_key(pred);
|
||||
item_set::iterator dit = orig_items.begin();
|
||||
item_set::iterator dend = orig_items.end();
|
||||
for (; dit!=dend; ++dit) {
|
||||
func_decl * master_pred = *dit;
|
||||
for (func_decl * master_pred : orig_items) {
|
||||
insert(master_pred, pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
iterator oit = o.begin();
|
||||
iterator oend = o.end();
|
||||
for (; oit!=oend; ++oit) {
|
||||
func_decl * pred = oit->m_key;
|
||||
item_set & orig_items = *oit->get_value();
|
||||
for (auto & kv : o) {
|
||||
func_decl * pred = kv.m_key;
|
||||
item_set & orig_items = *kv.get_value();
|
||||
m_data.insert(pred, alloc(item_set, orig_items));
|
||||
}
|
||||
}
|
||||
|
@ -86,14 +79,10 @@ namespace datalog {
|
|||
|
||||
void rule_dependencies::populate(const rule_set & rules) {
|
||||
SASSERT(m_data.empty());
|
||||
rule_set::decl2rules::iterator it = rules.m_head2rules.begin();
|
||||
rule_set::decl2rules::iterator end = rules.m_head2rules.end();
|
||||
for (; it != end; ++it) {
|
||||
ptr_vector<rule> * rules = it->m_value;
|
||||
ptr_vector<rule>::iterator it2 = rules->begin();
|
||||
ptr_vector<rule>::iterator end2 = rules->end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
populate(*it2);
|
||||
for (auto & kv : rules.m_head2rules) {
|
||||
ptr_vector<rule> * rules = kv.m_value;
|
||||
for (rule* r : *rules) {
|
||||
populate(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,54 +139,41 @@ namespace datalog {
|
|||
|
||||
void rule_dependencies::restrict(const item_set & allowed) {
|
||||
ptr_vector<func_decl> to_remove;
|
||||
iterator pit = begin();
|
||||
iterator pend = end();
|
||||
for (; pit!=pend; ++pit) {
|
||||
func_decl * pred = pit->m_key;
|
||||
for (auto const& kv : *this) {
|
||||
func_decl * pred = kv.m_key;
|
||||
if (!allowed.contains(pred)) {
|
||||
to_remove.insert(pred);
|
||||
continue;
|
||||
}
|
||||
item_set& itms = *pit->get_value();
|
||||
item_set& itms = *kv.get_value();
|
||||
set_intersection(itms, allowed);
|
||||
}
|
||||
ptr_vector<func_decl>::iterator rit = to_remove.begin();
|
||||
ptr_vector<func_decl>::iterator rend = to_remove.end();
|
||||
for (; rit != rend; ++rit) {
|
||||
remove_m_data_entry(*rit);
|
||||
}
|
||||
for (func_decl* f : to_remove)
|
||||
remove_m_data_entry(f);
|
||||
}
|
||||
|
||||
void rule_dependencies::remove(func_decl * itm) {
|
||||
remove_m_data_entry(itm);
|
||||
iterator pit = begin();
|
||||
iterator pend = end();
|
||||
for (; pit != pend; ++pit) {
|
||||
item_set & itms = *pit->get_value();
|
||||
for (auto const& kv : *this) {
|
||||
item_set & itms = *kv.get_value();
|
||||
itms.remove(itm);
|
||||
}
|
||||
}
|
||||
|
||||
void rule_dependencies::remove(const item_set & to_remove) {
|
||||
item_set::iterator rit = to_remove.begin();
|
||||
item_set::iterator rend = to_remove.end();
|
||||
for (; rit!=rend; ++rit) {
|
||||
remove_m_data_entry(*rit);
|
||||
for (auto * item : to_remove) {
|
||||
remove_m_data_entry(item);
|
||||
}
|
||||
iterator pit = begin();
|
||||
iterator pend = end();
|
||||
for (; pit!=pend; ++pit) {
|
||||
item_set * itms = pit->get_value();
|
||||
for (auto & kv : *this) {
|
||||
item_set * itms = kv.get_value();
|
||||
set_difference(*itms, to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned rule_dependencies::out_degree(func_decl * f) const {
|
||||
unsigned res = 0;
|
||||
iterator pit = begin();
|
||||
iterator pend = end();
|
||||
for (; pit!=pend; ++pit) {
|
||||
item_set & itms = *pit->get_value();
|
||||
for (auto & kv : *this) {
|
||||
item_set & itms = *kv.get_value();
|
||||
if (itms.contains(f)) {
|
||||
res++;
|
||||
}
|
||||
|
@ -333,19 +309,11 @@ namespace datalog {
|
|||
void rule_set::inherit_predicates(rule_set const& other) {
|
||||
m_refs.append(other.m_refs);
|
||||
set_union(m_output_preds, other.m_output_preds);
|
||||
{
|
||||
obj_map<func_decl, func_decl*>::iterator it = other.m_orig2pred.begin();
|
||||
obj_map<func_decl, func_decl*>::iterator end = other.m_orig2pred.end();
|
||||
for (; it != end; ++it) {
|
||||
m_orig2pred.insert(it->m_key, it->m_value);
|
||||
}
|
||||
for (auto & kv : other.m_orig2pred) {
|
||||
m_orig2pred.insert(kv.m_key, kv.m_value);
|
||||
}
|
||||
{
|
||||
obj_map<func_decl, func_decl*>::iterator it = other.m_pred2orig.begin();
|
||||
obj_map<func_decl, func_decl*>::iterator end = other.m_pred2orig.end();
|
||||
for (; it != end; ++it) {
|
||||
m_pred2orig.insert(it->m_key, it->m_value);
|
||||
}
|
||||
for (auto & kv : other.m_pred2orig) {
|
||||
m_pred2orig.insert(kv.m_key, kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,26 +505,19 @@ namespace datalog {
|
|||
void rule_set::display_deps( std::ostream & out ) const
|
||||
{
|
||||
const pred_set_vector & strats = get_strats();
|
||||
pred_set_vector::const_iterator sit = strats.begin();
|
||||
pred_set_vector::const_iterator send = strats.end();
|
||||
for (; sit!=send; ++sit) {
|
||||
func_decl_set & strat = **sit;
|
||||
func_decl_set::iterator fit=strat.begin();
|
||||
func_decl_set::iterator fend=strat.end();
|
||||
bool non_empty = false;
|
||||
for (; fit!=fend; ++fit) {
|
||||
func_decl * first = *fit;
|
||||
const func_decl_set & deps = m_deps.get_deps(first);
|
||||
func_decl_set::iterator dit=deps.begin();
|
||||
func_decl_set::iterator dend=deps.end();
|
||||
for (; dit!=dend; ++dit) {
|
||||
non_empty = true;
|
||||
func_decl * dep = *dit;
|
||||
out<<first->get_name()<<" -> "<<dep->get_name()<<"\n";
|
||||
}
|
||||
}
|
||||
if (non_empty && sit!=send) {
|
||||
bool non_empty = false;
|
||||
for (func_decl_set* strat : strats) {
|
||||
if (non_empty) {
|
||||
out << "\n";
|
||||
non_empty = false;
|
||||
}
|
||||
|
||||
for (func_decl * first : *strat) {
|
||||
const func_decl_set & deps = m_deps.get_deps(first);
|
||||
for (func_decl * dep : deps) {
|
||||
non_empty = true;
|
||||
out<<first->get_name()<<" -> " <<dep->get_name()<<"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -568,11 +529,8 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
rule_stratifier::~rule_stratifier() {
|
||||
comp_vector::iterator it = m_strats.begin();
|
||||
comp_vector::iterator end = m_strats.end();
|
||||
for (; it!=end; ++it) {
|
||||
SASSERT(*it);
|
||||
dealloc(*it);
|
||||
for (auto * t : m_strats) {
|
||||
dealloc(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,10 +575,8 @@ namespace datalog {
|
|||
m_stack_P.push_back(el);
|
||||
|
||||
const item_set & children = m_deps.get_deps(el);
|
||||
item_set::iterator cit=children.begin();
|
||||
item_set::iterator cend=children.end();
|
||||
for (; cit!=cend; ++cit) {
|
||||
traverse(*cit);
|
||||
for (T* ch : children) {
|
||||
traverse(ch);
|
||||
}
|
||||
|
||||
if (el == m_stack_P.back()) {
|
||||
|
@ -646,10 +602,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
//detect strong components
|
||||
rule_dependencies::iterator it = m_deps.begin();
|
||||
rule_dependencies::iterator end = m_deps.end();
|
||||
for (; it!=end; ++it) {
|
||||
T * el = it->m_key;
|
||||
for (auto const& kv : m_deps) {
|
||||
T * el = kv.m_key;
|
||||
//we take a note of the preorder number with which this sweep started
|
||||
m_first_preorder = m_next_preorder;
|
||||
traverse(el);
|
||||
|
@ -662,19 +616,13 @@ namespace datalog {
|
|||
in_degrees.resize(m_components.size());
|
||||
|
||||
//init in_degrees
|
||||
it = m_deps.begin();
|
||||
end = m_deps.end();
|
||||
for (; it != end; ++it) {
|
||||
T * el = it->m_key;
|
||||
item_set * out_edges = it->m_value;
|
||||
for (auto const& kv : m_deps) {
|
||||
T * el = kv.m_key;
|
||||
item_set * out_edges = kv.m_value;
|
||||
|
||||
unsigned el_comp = 0;
|
||||
VERIFY( m_component_nums.find(el, el_comp) );
|
||||
unsigned el_comp = m_component_nums[el];
|
||||
|
||||
item_set::iterator eit = out_edges->begin();
|
||||
item_set::iterator eend = out_edges->end();
|
||||
for (; eit!=eend; ++eit) {
|
||||
T * tgt = *eit;
|
||||
for (T * tgt : *out_edges) {
|
||||
|
||||
unsigned tgt_comp = m_component_nums.find(tgt);
|
||||
|
||||
|
@ -701,15 +649,9 @@ namespace datalog {
|
|||
unsigned strats_index = 0;
|
||||
while (strats_index < m_strats.size()) { //m_strats.size() changes inside the loop!
|
||||
item_set * comp = m_strats[strats_index];
|
||||
item_set::iterator cit=comp->begin();
|
||||
item_set::iterator cend=comp->end();
|
||||
for (; cit!=cend; ++cit) {
|
||||
T * el = *cit;
|
||||
for (T * el : *comp) {
|
||||
const item_set & deps = m_deps.get_deps(el);
|
||||
item_set::iterator eit=deps.begin();
|
||||
item_set::iterator eend=deps.end();
|
||||
for (; eit!=eend; ++eit) {
|
||||
T * tgt = *eit;
|
||||
for (T * tgt : deps) {
|
||||
unsigned tgt_comp = 0;
|
||||
VERIFY( m_component_nums.find(tgt, tgt_comp) );
|
||||
|
||||
|
@ -724,7 +666,7 @@ namespace datalog {
|
|||
m_components[tgt_comp] = 0;
|
||||
}
|
||||
}
|
||||
traverse(*cit);
|
||||
traverse(el);
|
||||
}
|
||||
}
|
||||
strats_index++;
|
||||
|
@ -738,12 +680,9 @@ namespace datalog {
|
|||
|
||||
SASSERT(m_pred_strat_nums.empty());
|
||||
unsigned strat_cnt = m_strats.size();
|
||||
for (unsigned strat_index=0; strat_index<strat_cnt; strat_index++) {
|
||||
for (unsigned strat_index=0; strat_index < strat_cnt; strat_index++) {
|
||||
item_set * comp = m_strats[strat_index];
|
||||
item_set::iterator cit=comp->begin();
|
||||
item_set::iterator cend=comp->end();
|
||||
for (; cit != cend; ++cit) {
|
||||
T * el = *cit;
|
||||
for (T * el : *comp) {
|
||||
m_pred_strat_nums.insert(el, strat_index);
|
||||
}
|
||||
}
|
||||
|
@ -761,10 +700,8 @@ namespace datalog {
|
|||
m_deps.display(out << "dependencies\n");
|
||||
out << "strata\n";
|
||||
for (unsigned i = 0; i < m_strats.size(); ++i) {
|
||||
item_set::iterator it = m_strats[i]->begin();
|
||||
item_set::iterator end = m_strats[i]->end();
|
||||
for (; it != end; ++it) {
|
||||
out << (*it)->get_name() << " ";
|
||||
for (auto * item : *m_strats[i]) {
|
||||
out << item->get_name() << " ";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
|
|
@ -115,8 +115,7 @@ namespace datalog {
|
|||
expr_ref tmp(m);
|
||||
for (unsigned i = 0; i < tgt.size(); ++i) {
|
||||
if (tgt[i].get()) {
|
||||
vs(tgt[i].get(), sub.size(), sub.c_ptr(), tmp);
|
||||
tgt[i] = tmp;
|
||||
tgt[i] = vs(tgt[i].get(), sub.size(), sub.c_ptr());
|
||||
}
|
||||
else {
|
||||
tgt[i] = sub[i];
|
||||
|
|
|
@ -108,20 +108,20 @@ namespace datalog {
|
|||
// apply substitution to body.
|
||||
var_subst vs(m, false);
|
||||
for (unsigned k = 0; k < p->get_arity(); ++k) {
|
||||
vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), trm);
|
||||
trm = vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(m.mk_eq(trm, mk_q_arg(p, k, true)));
|
||||
}
|
||||
for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) {
|
||||
func_decl* q = r.get_decl(j);
|
||||
for (unsigned k = 0; k < q->get_arity(); ++k) {
|
||||
vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), trm);
|
||||
trm = vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(m.mk_eq(trm, mk_q_arg(q, k, false)));
|
||||
}
|
||||
func_decl_ref qr = mk_q_func_decl(q);
|
||||
conjs.push_back(m.mk_app(qr, m_bv.mk_bv_sub(var, mk_q_one())));
|
||||
}
|
||||
for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) {
|
||||
vs(r.get_tail(j), sub.size(), sub.c_ptr(), trm);
|
||||
trm = vs(r.get_tail(j), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(trm);
|
||||
}
|
||||
if (r.get_uninterpreted_tail_size() > 0) {
|
||||
|
@ -238,7 +238,7 @@ namespace datalog {
|
|||
var_subst vs(m, false);
|
||||
num = mk_q_num(i);
|
||||
expr* nums[1] = { num };
|
||||
vs(t, 1, nums, tmp);
|
||||
tmp = vs(t, 1, nums);
|
||||
return (*model)(tmp);
|
||||
}
|
||||
|
||||
|
@ -535,7 +535,7 @@ namespace datalog {
|
|||
for (unsigned j = 0; j < sz; ++j) {
|
||||
func_decl* head_j = r->get_decl(j);
|
||||
app* body_j = r->get_tail(j);
|
||||
vs(body_j, sub.size(), sub.c_ptr(), prop_body);
|
||||
prop_body = vs(body_j, sub.size(), sub.c_ptr());
|
||||
prs.push_back(get_proof(md, head_j, to_app(prop_body), level-1));
|
||||
positions.push_back(std::make_pair(j+1,0));
|
||||
substs.push_back(expr_ref_vector(m));
|
||||
|
@ -609,11 +609,9 @@ namespace datalog {
|
|||
}
|
||||
|
||||
expr_ref skolemize_vars(rule& r, expr_ref_vector const& args, ptr_vector<sort> const& vars, expr* e) {
|
||||
expr_ref result(m);
|
||||
expr_ref_vector binding = mk_skolem_binding(r, vars, args);
|
||||
var_subst vs(m, false);
|
||||
vs(e, binding.size(), binding.c_ptr(), result);
|
||||
return result;
|
||||
return vs(e, binding.size(), binding.c_ptr());
|
||||
}
|
||||
|
||||
func_decl_ref mk_body_func(rule& r, ptr_vector<sort> const& args, unsigned index, sort* s) {
|
||||
|
@ -646,8 +644,8 @@ namespace datalog {
|
|||
return expr_ref(e, m);
|
||||
}
|
||||
var_subst vs(m, false);
|
||||
vs(e, binding.size(), binding.c_ptr(), tmp);
|
||||
vs(pat, binding.size(), binding.c_ptr(), head);
|
||||
tmp = vs(e, binding.size(), binding.c_ptr());
|
||||
head = vs(pat, binding.size(), binding.c_ptr());
|
||||
patterns.push_back(m.mk_pattern(to_app(head)));
|
||||
symbol qid, skid;
|
||||
return expr_ref(m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp, 1, qid, skid, 1, patterns.c_ptr()), m);
|
||||
|
@ -892,7 +890,7 @@ namespace datalog {
|
|||
// apply substitution to body.
|
||||
var_subst vs(m, false);
|
||||
for (unsigned k = 0; k < p->get_arity(); ++k) {
|
||||
vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr());
|
||||
expr_ref arg = mk_arg(p, k, path_var, trace_arg);
|
||||
conjs.push_back(m.mk_eq(tmp, arg));
|
||||
}
|
||||
|
@ -906,7 +904,7 @@ namespace datalog {
|
|||
}
|
||||
func_decl* q = r.get_decl(j);
|
||||
for (unsigned k = 0; k < q->get_arity(); ++k) {
|
||||
vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr());
|
||||
expr_ref arg = mk_arg(q, k, path_arg, vars[j].get());
|
||||
conjs.push_back(m.mk_eq(tmp, arg));
|
||||
}
|
||||
|
@ -914,7 +912,7 @@ namespace datalog {
|
|||
conjs.push_back(m.mk_app(q_pred, vars[j].get(), path_arg));
|
||||
}
|
||||
for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) {
|
||||
vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_tail(j), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(tmp);
|
||||
}
|
||||
bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body);
|
||||
|
@ -1048,7 +1046,7 @@ namespace datalog {
|
|||
expr_ref fml(m), head(m), tmp(m);
|
||||
app_ref path1(m);
|
||||
|
||||
var_subst vs(m, false);
|
||||
// var_subst vs(m, false);
|
||||
mk_subst(*rules[i], path, trace, sub);
|
||||
rm.to_formula(*rules[i], fml);
|
||||
prs.push_back(rules[i]->get_proof());
|
||||
|
@ -1399,20 +1397,20 @@ namespace datalog {
|
|||
// apply substitution to body.
|
||||
var_subst vs(m, false);
|
||||
for (unsigned k = 0; k < p->get_arity(); ++k) {
|
||||
vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(m.mk_eq(tmp, mk_level_arg(p, k, level)));
|
||||
}
|
||||
for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) {
|
||||
SASSERT(level > 0);
|
||||
func_decl* q = r.get_decl(j);
|
||||
for (unsigned k = 0; k < q->get_arity(); ++k) {
|
||||
vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(m.mk_eq(tmp, mk_level_arg(q, k, level-1)));
|
||||
}
|
||||
conjs.push_back(mk_level_predicate(q, level-1));
|
||||
}
|
||||
for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) {
|
||||
vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp);
|
||||
tmp = vs(r.get_tail(j), sub.size(), sub.c_ptr());
|
||||
conjs.push_back(tmp);
|
||||
}
|
||||
bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body);
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace datalog {
|
|||
m_ground[i] = m.mk_fresh_const("c", fv[i]);
|
||||
}
|
||||
}
|
||||
m_var_subst(e, m_ground.size(), m_ground.c_ptr(), e);
|
||||
e = m_var_subst(e, m_ground.size(), m_ground.c_ptr());
|
||||
}
|
||||
|
||||
static bool rule_sort_fn(const rule *r1, const rule *r2) {
|
||||
|
|
|
@ -59,9 +59,7 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < sig.size(); ++i) {
|
||||
vars.push_back(m.mk_const(symbol(i), sig[i]));
|
||||
}
|
||||
expr_ref result(m);
|
||||
sub(fml, vars.size(), vars.c_ptr(), result);
|
||||
return result;
|
||||
return sub(fml, vars.size(), vars.c_ptr());
|
||||
}
|
||||
|
||||
void check_relation::add_fact(const relation_fact & f) {
|
||||
|
@ -292,7 +290,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
var_subst sub(m, false);
|
||||
sub(fml, vars.size(), vars.c_ptr(), fml1);
|
||||
fml1 = sub(fml, vars.size(), vars.c_ptr());
|
||||
bound.reverse();
|
||||
fml1 = m.mk_exists(bound.size(), bound.c_ptr(), names.c_ptr(), fml1);
|
||||
return fml1;
|
||||
|
@ -333,7 +331,7 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < sig2.size(); ++i) {
|
||||
vars.push_back(m.mk_var(i + sig1.size(), sig2[i]));
|
||||
}
|
||||
sub(fml2, vars.size(), vars.c_ptr(), fml2);
|
||||
fml2 = sub(fml2, vars.size(), vars.c_ptr());
|
||||
fml1 = m.mk_and(fml1, fml2);
|
||||
for (unsigned i = 0; i < cols1.size(); ++i) {
|
||||
unsigned v1 = cols1[i];
|
||||
|
@ -372,14 +370,14 @@ namespace datalog {
|
|||
expr_ref fml1(m), fml2(m);
|
||||
src.to_formula(fml1);
|
||||
dst.to_formula(fml2);
|
||||
subst(fml1, sub.size(), sub.c_ptr(), fml1);
|
||||
fml1 = subst(fml1, sub.size(), sub.c_ptr());
|
||||
expr_ref_vector vars(m);
|
||||
for (unsigned i = 0; i < sig2.size(); ++i) {
|
||||
vars.push_back(m.mk_const(symbol(i), sig2[i]));
|
||||
}
|
||||
|
||||
subst(fml1, vars.size(), vars.c_ptr(), fml1);
|
||||
subst(fml2, vars.size(), vars.c_ptr(), fml2);
|
||||
fml1 = subst(fml1, vars.size(), vars.c_ptr());
|
||||
fml2 = subst(fml2, vars.size(), vars.c_ptr());
|
||||
|
||||
check_equiv("permutation", fml1, fml2);
|
||||
}
|
||||
|
@ -405,8 +403,8 @@ namespace datalog {
|
|||
strm << "x" << i;
|
||||
vars.push_back(m.mk_const(symbol(strm.str().c_str()), sig[i]));
|
||||
}
|
||||
sub(fml1, vars.size(), vars.c_ptr(), fml1);
|
||||
sub(fml2, vars.size(), vars.c_ptr(), fml2);
|
||||
fml1 = sub(fml1, vars.size(), vars.c_ptr());
|
||||
fml2 = sub(fml2, vars.size(), vars.c_ptr());
|
||||
check_equiv("filter", fml1, fml2);
|
||||
}
|
||||
|
||||
|
@ -453,8 +451,8 @@ namespace datalog {
|
|||
strm << "x" << i;
|
||||
vars.push_back(m.mk_const(symbol(strm.str().c_str()), sig[i]));
|
||||
}
|
||||
sub(fml1, vars.size(), vars.c_ptr(), fml1);
|
||||
sub(fml2, vars.size(), vars.c_ptr(), fml2);
|
||||
fml1 = sub(fml1, vars.size(), vars.c_ptr());
|
||||
fml2 = sub(fml2, vars.size(), vars.c_ptr());
|
||||
|
||||
check_equiv("union", fml1, fml2);
|
||||
|
||||
|
@ -466,13 +464,13 @@ namespace datalog {
|
|||
// dst \ dst0 == delta & dst & \ dst0
|
||||
expr_ref fml4(m), fml5(m);
|
||||
fml4 = m.mk_and(fml2, m.mk_not(dst0));
|
||||
sub(fml4, vars.size(), vars.c_ptr(), fml4);
|
||||
sub(d, vars.size(), vars.c_ptr(), d);
|
||||
fml4 = sub(fml4, vars.size(), vars.c_ptr());
|
||||
d = sub(d, vars.size(), vars.c_ptr());
|
||||
check_contains("union_delta low", d, fml4);
|
||||
//
|
||||
// delta >= delta0
|
||||
//
|
||||
sub(delta0, vars.size(), vars.c_ptr(), d0);
|
||||
d0 = sub(delta0, vars.size(), vars.c_ptr());
|
||||
check_contains("union delta0", d, d0);
|
||||
|
||||
//
|
||||
|
@ -480,8 +478,8 @@ namespace datalog {
|
|||
//
|
||||
fml4 = m.mk_or(fml2, delta0);
|
||||
fml5 = m.mk_or(d, dst0);
|
||||
sub(fml4, vars.size(), vars.c_ptr(), fml4);
|
||||
sub(fml5, vars.size(), vars.c_ptr(), fml5);
|
||||
fml4 = sub(fml4, vars.size(), vars.c_ptr());
|
||||
fml5 = sub(fml5, vars.size(), vars.c_ptr());
|
||||
check_equiv("union no overflow", fml4, fml5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -725,8 +725,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
expr_ref renamed(m);
|
||||
m_context.get_var_subst()(filter_cond, binding.size(), binding.c_ptr(), renamed);
|
||||
expr_ref renamed = m_context.get_var_subst()(filter_cond, binding.size(), binding.c_ptr());
|
||||
app_ref app_renamed(to_app(renamed), m);
|
||||
if (remove_columns.empty()) {
|
||||
if (!dealloc)
|
||||
|
|
|
@ -1311,8 +1311,7 @@ namespace datalog {
|
|||
if(m_rel_cond_columns.empty()) {
|
||||
expr_ref_vector renaming(m_manager);
|
||||
get_renaming_args(r.m_sig2table, r.get_signature(), renaming);
|
||||
expr_ref table_cond(m_manager);
|
||||
m_subst(condition, renaming.size(), renaming.c_ptr(), table_cond);
|
||||
expr_ref table_cond = m_subst(condition, renaming.size(), renaming.c_ptr());
|
||||
m_table_filter = rmgr.mk_filter_interpreted_fn(r.get_table(), to_app(table_cond));
|
||||
}
|
||||
else {
|
||||
|
@ -1361,9 +1360,7 @@ namespace datalog {
|
|||
continue;
|
||||
}
|
||||
if(!m_rel_filter) {
|
||||
expr_ref inner_cond(m_manager);
|
||||
m_subst(m_cond, m_renaming_for_inner_rel.size(), m_renaming_for_inner_rel.c_ptr(),
|
||||
inner_cond);
|
||||
expr_ref inner_cond = m_subst(m_cond, m_renaming_for_inner_rel.size(), m_renaming_for_inner_rel.c_ptr());
|
||||
m_rel_filter = rmgr.mk_filter_interpreted_fn(*inner, to_app(inner_cond));
|
||||
}
|
||||
(*m_rel_filter)(*inner);
|
||||
|
@ -1411,11 +1408,10 @@ namespace datalog {
|
|||
|
||||
//create the condition with table values substituted in and relation values properly renamed
|
||||
expr_ref inner_cond(m_manager);
|
||||
m_subst(m_cond, m_renaming_for_inner_rel.size(), m_renaming_for_inner_rel.c_ptr(),
|
||||
inner_cond);
|
||||
inner_cond = m_subst(m_cond, m_renaming_for_inner_rel.size(), m_renaming_for_inner_rel.c_ptr());
|
||||
|
||||
relation_base * new_rel = old_rel.clone();
|
||||
|
||||
|
||||
scoped_ptr<relation_mutator_fn> filter = rmgr.mk_filter_interpreted_fn(*new_rel, to_app(inner_cond));
|
||||
(*filter)(*new_rel);
|
||||
|
||||
|
|
|
@ -471,8 +471,7 @@ namespace datalog {
|
|||
SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
|
||||
subst_arg[ofs-i] = r.m_data.get(i);
|
||||
}
|
||||
expr_ref res(m_manager);
|
||||
m_subst(m_new_rule, subst_arg.size(), subst_arg.c_ptr(), res);
|
||||
expr_ref res = m_subst(m_new_rule, subst_arg.size(), subst_arg.c_ptr());
|
||||
r.m_data[m_col_idx] = to_app(res);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -246,8 +246,8 @@ namespace datalog {
|
|||
get_normalizer(t1, t2, norm_subst);
|
||||
expr_ref t1n_ref(m);
|
||||
expr_ref t2n_ref(m);
|
||||
m_var_subst(t1, norm_subst.size(), norm_subst.c_ptr(), t1n_ref);
|
||||
m_var_subst(t2, norm_subst.size(), norm_subst.c_ptr(), t2n_ref);
|
||||
t1n_ref = m_var_subst(t1, norm_subst.size(), norm_subst.c_ptr());
|
||||
t2n_ref = m_var_subst(t2, norm_subst.size(), norm_subst.c_ptr());
|
||||
app * t1n = to_app(t1n_ref);
|
||||
app * t2n = to_app(t2n_ref);
|
||||
if (t1n->get_id() > t2n->get_id()) {
|
||||
|
@ -531,7 +531,7 @@ namespace datalog {
|
|||
expr_ref_vector denormalizer(m);
|
||||
reverse_renaming(m, normalizer, denormalizer);
|
||||
expr_ref new_transf(m);
|
||||
m_var_subst(t_new, denormalizer.size(), denormalizer.c_ptr(), new_transf);
|
||||
new_transf = m_var_subst(t_new, denormalizer.size(), denormalizer.c_ptr());
|
||||
app * new_lit = to_app(new_transf);
|
||||
|
||||
m_pinned.push_back(new_lit);
|
||||
|
|
|
@ -1395,8 +1395,7 @@ namespace datalog {
|
|||
args.push_back(m_decl_util.mk_numeral(el, m_free_vars[i]));
|
||||
}
|
||||
|
||||
expr_ref ground(m_ast_manager);
|
||||
m_vs(m_condition.get(), args.size(), args.c_ptr(), ground);
|
||||
expr_ref ground = m_vs(m_condition.get(), args.size(), args.c_ptr());
|
||||
m_simp(ground);
|
||||
|
||||
return m_ast_manager.is_false(ground);
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace datalog {
|
|||
s.push_back(m.mk_var(idx, sig[i]));
|
||||
}
|
||||
get_inner().to_formula(tmp);
|
||||
get_plugin().get_context().get_var_subst()(tmp, sz, s.c_ptr(), fml);
|
||||
fml = get_plugin().get_context().get_var_subst()(tmp, sz, s.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
|
@ -584,8 +584,7 @@ namespace datalog {
|
|||
}
|
||||
subst_vect[subst_ofs-i] = m.mk_var(r.m_sig2inner[i], sig[i]);
|
||||
}
|
||||
expr_ref inner_cond(m);
|
||||
get_context().get_var_subst()(condition, subst_vect.size(), subst_vect.c_ptr(), inner_cond);
|
||||
expr_ref inner_cond = get_context().get_var_subst()(condition, subst_vect.size(), subst_vect.c_ptr());
|
||||
|
||||
relation_mutator_fn * inner_fun = get_manager().mk_filter_interpreted_fn(r.get_inner(), to_app(inner_cond));
|
||||
if(!inner_fun) {
|
||||
|
|
|
@ -526,7 +526,7 @@ void lemma::mk_expr_core() {
|
|||
sorts.push_back(get_sort(zks.get(i)));
|
||||
names.push_back(zks.get(i)->get_decl()->get_name());
|
||||
}
|
||||
m_body = m.mk_quantifier(true, zks.size(),
|
||||
m_body = m.mk_quantifier(forall_k, zks.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
m_body, 15, symbol(m_body->get_id()));
|
||||
|
@ -633,7 +633,7 @@ void lemma::instantiate(expr * const * exprs, expr_ref &result, expr *e) {
|
|||
expr *body = to_quantifier(lem)->get_expr();
|
||||
unsigned num_decls = to_quantifier(lem)->get_num_decls();
|
||||
var_subst vs(m, false);
|
||||
vs(body, num_decls, exprs, result);
|
||||
result = vs(body, num_decls, exprs);
|
||||
}
|
||||
|
||||
void lemma::set_level (unsigned lvl) {
|
||||
|
@ -1347,7 +1347,7 @@ lbool pred_transformer::is_reachable(pob& n, expr_ref_vector* core,
|
|||
|
||||
if (is_sat == l_true || is_sat == l_undef) {
|
||||
if (core) { core->reset(); }
|
||||
if (model && model->get()) {
|
||||
if (model) {
|
||||
r = find_rule(**model, is_concrete, reach_pred_used, num_reuse_reach);
|
||||
TRACE ("spacer", tout << "reachable "
|
||||
<< "is_concrete " << is_concrete << " rused: ";
|
||||
|
@ -1621,9 +1621,7 @@ void pred_transformer::init_rule(decl2rel const& pts, datalog::rule const& rule)
|
|||
ground_free_vars(trans, var_reprs, aux_vars, ut_size == 0);
|
||||
SASSERT(is_all_non_null(var_reprs));
|
||||
|
||||
expr_ref tmp(m);
|
||||
var_subst(m, false)(trans, var_reprs.size (),
|
||||
(expr*const*)var_reprs.c_ptr(), tmp);
|
||||
expr_ref tmp = var_subst(m, false)(trans, var_reprs.size (), (expr*const*)var_reprs.c_ptr());
|
||||
flatten_and (tmp, side);
|
||||
trans = mk_and(side);
|
||||
side.reset ();
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
bool is_h_marked(proof* p) {return m_h_mark.is_marked(p);}
|
||||
|
||||
bool is_b_pure (proof *p) {
|
||||
return !is_h_marked(p) && !this->is_a_marked(p) && is_core_pure(m.get_fact(p));
|
||||
return !is_h_marked (p) && !this->is_a_marked(p) && is_core_pure(m.get_fact (p));
|
||||
}
|
||||
|
||||
void display_dot(std::ostream &out);
|
||||
|
|
|
@ -322,24 +322,6 @@ void iuc_solver::get_iuc(expr_ref_vector &core)
|
|||
// -- new hypothesis reducer
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
static unsigned bcnt = 0;
|
||||
{
|
||||
bcnt++;
|
||||
TRACE("spacer", tout << "Dumping pf bcnt: " << bcnt << "\n";);
|
||||
if (bcnt == 123) {
|
||||
std::ofstream ofs;
|
||||
ofs.open("/tmp/bpf_" + std::to_string(bcnt) + ".dot");
|
||||
iuc_proof iuc_pf_before(m, res.get(), core_lits);
|
||||
iuc_pf_before.display_dot(ofs);
|
||||
ofs.close();
|
||||
|
||||
proof_checker pc(m);
|
||||
expr_ref_vector side(m);
|
||||
ENSURE(pc.check(res, side));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
scoped_watch _t_ (m_hyp_reduce2_sw);
|
||||
|
||||
// pre-process proof for better iuc extraction
|
||||
|
@ -374,22 +356,6 @@ void iuc_solver::get_iuc(expr_ref_vector &core)
|
|||
|
||||
iuc_proof iuc_pf(m, res, core_lits);
|
||||
|
||||
#if 0
|
||||
static unsigned cnt = 0;
|
||||
{
|
||||
cnt++;
|
||||
TRACE("spacer", tout << "Dumping pf cnt: " << cnt << "\n";);
|
||||
if (cnt == 123) {
|
||||
std::ofstream ofs;
|
||||
ofs.open("/tmp/pf_" + std::to_string(cnt) + ".dot");
|
||||
iuc_pf.display_dot(ofs);
|
||||
ofs.close();
|
||||
proof_checker pc(m);
|
||||
expr_ref_vector side(m);
|
||||
ENSURE(pc.check(res, side));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
unsat_core_learner learner(m, iuc_pf);
|
||||
|
||||
unsat_core_plugin* plugin;
|
||||
|
|
|
@ -785,7 +785,7 @@ namespace {
|
|||
|
||||
void ground_expr(expr *e, expr_ref &out, app_ref_vector &vars) {
|
||||
expr_free_vars fv;
|
||||
ast_manager &m = out.get_manager();
|
||||
ast_manager &m = out.m();
|
||||
|
||||
fv(e);
|
||||
if (vars.size() < fv.size()) {
|
||||
|
@ -795,7 +795,7 @@ namespace {
|
|||
sort *s = fv[i] ? fv[i] : m.mk_bool_sort();
|
||||
vars[i] = mk_zk_const(m, i, s);
|
||||
var_subst vs(m, false);
|
||||
vs(e, vars.size(),(expr * *) vars.c_ptr(), out);
|
||||
out = vs(e, vars.size(),(expr * *) vars.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -561,13 +561,13 @@ namespace tb {
|
|||
}
|
||||
vars.push_back(m.mk_const(symbol(i), sorts[i]));
|
||||
}
|
||||
vs(g.get_head(), vars.size(), vars.c_ptr(), fml);
|
||||
fml = vs(g.get_head(), vars.size(), vars.c_ptr());
|
||||
m_head = to_app(fml);
|
||||
for (unsigned i = 0; i < g.get_num_predicates(); ++i) {
|
||||
vs(g.get_predicate(i), vars.size(), vars.c_ptr(), fml);
|
||||
fml = vs(g.get_predicate(i), vars.size(), vars.c_ptr());
|
||||
m_preds.push_back(to_app(fml));
|
||||
}
|
||||
vs(g.get_constraint(), vars.size(), vars.c_ptr(), fml);
|
||||
fml = vs(g.get_constraint(), vars.size(), vars.c_ptr());
|
||||
fmls.push_back(fml);
|
||||
m_precond = m.mk_and(fmls.size(), fmls.c_ptr());
|
||||
IF_VERBOSE(2,
|
||||
|
@ -1132,12 +1132,12 @@ namespace tb {
|
|||
}
|
||||
}
|
||||
if (change) {
|
||||
m_S2(result->get_constraint(), m_rename.size(), m_rename.c_ptr(), constraint);
|
||||
constraint = m_S2(result->get_constraint(), m_rename.size(), m_rename.c_ptr());
|
||||
for (unsigned i = 0; i < result->get_num_predicates(); ++i) {
|
||||
m_S2(result->get_predicate(i), m_rename.size(), m_rename.c_ptr(), tmp);
|
||||
tmp = m_S2(result->get_predicate(i), m_rename.size(), m_rename.c_ptr());
|
||||
predicates[i] = to_app(tmp);
|
||||
}
|
||||
m_S2(result->get_head(), m_rename.size(), m_rename.c_ptr(), tmp);
|
||||
tmp = m_S2(result->get_head(), m_rename.size(), m_rename.c_ptr());
|
||||
head = to_app(tmp);
|
||||
result->init(head, predicates, constraint);
|
||||
}
|
||||
|
@ -1168,7 +1168,7 @@ namespace tb {
|
|||
if (vars[i]) {
|
||||
v = m.mk_var(i, vars[i]);
|
||||
m_S1.apply(2, delta, expr_offset(v, offset), tmp);
|
||||
m_S2(tmp, m_rename.size(), m_rename.c_ptr(), tmp);
|
||||
tmp = m_S2(tmp, m_rename.size(), m_rename.c_ptr());
|
||||
insert_subst(offset, tmp);
|
||||
}
|
||||
else {
|
||||
|
@ -1613,8 +1613,8 @@ namespace datalog {
|
|||
}
|
||||
expr_ref body = clause.get_body();
|
||||
var_subst vs(m, false);
|
||||
vs(body, subst.size(), subst.c_ptr(), body);
|
||||
out << mk_pp(body, m) << "\n";
|
||||
body = vs(body, subst.size(), subst.c_ptr());
|
||||
out << body << "\n";
|
||||
}
|
||||
|
||||
void resolve_rule(replace_proof_converter& pc, tb::clause const& r1, tb::clause const& r2,
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace datalog {
|
|||
}
|
||||
var_subst vs(m, false);
|
||||
for (unsigned i = r->get_uninterpreted_tail_size(); i < r->get_tail_size(); ++i) {
|
||||
vs(r->get_tail(i), revsub.size(), revsub.c_ptr(), result);
|
||||
result = vs(r->get_tail(i), revsub.size(), revsub.c_ptr());
|
||||
conjs.push_back(result);
|
||||
}
|
||||
bwr.mk_and(conjs.size(), conjs.c_ptr(), result);
|
||||
|
|
|
@ -156,8 +156,7 @@ namespace datalog {
|
|||
SASSERT(m_binding[i]);
|
||||
});
|
||||
m_binding.reverse();
|
||||
expr_ref res(m);
|
||||
instantiate(m, q, m_binding.c_ptr(), res);
|
||||
expr_ref res = instantiate(m, q, m_binding.c_ptr());
|
||||
m_binding.reverse();
|
||||
m_cnst2var(res);
|
||||
conjs.push_back(res);
|
||||
|
@ -222,10 +221,7 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < qs.size(); ++i) {
|
||||
instantiate_quantifier(qs[i].get(), conjs);
|
||||
}
|
||||
obj_map<func_decl, ptr_vector<expr>*>::iterator it = m_funs.begin(), end = m_funs.end();
|
||||
for (; it != end; ++it) {
|
||||
dealloc(it->m_value);
|
||||
}
|
||||
for (auto & kv : m_funs) dealloc(kv.m_value);
|
||||
m_funs.reset();
|
||||
|
||||
fml = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace datalog {
|
|||
// Hedge that we don't have to handle the general case for models produced
|
||||
// by Horn clause solvers.
|
||||
SASSERT(!new_fi->is_partial() && new_fi->num_entries() == 0);
|
||||
vs(new_fi->get_else(), subst.size(), subst.c_ptr(), tmp);
|
||||
tmp = vs(new_fi->get_else(), subst.size(), subst.c_ptr());
|
||||
old_fi->set_else(tmp);
|
||||
old_model->register_decl(old_p, old_fi);
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@ namespace datalog {
|
|||
}
|
||||
if (!new_fi->is_partial()) {
|
||||
TRACE("dl", tout << mk_pp(new_fi->get_else(), m) << "\n";);
|
||||
vs(new_fi->get_else(), subst.size(), subst.c_ptr(), tmp);
|
||||
tmp = vs(new_fi->get_else(), subst.size(), subst.c_ptr());
|
||||
old_fi->set_else(tmp);
|
||||
}
|
||||
unsigned num_entries = new_fi->num_entries();
|
||||
|
@ -362,7 +362,7 @@ namespace datalog {
|
|||
func_entry const* e = new_fi->get_entry(j);
|
||||
for (unsigned k = 0, l = 0; k < old_p->get_arity(); ++k) {
|
||||
if (!is_sliced.get(k)) {
|
||||
vs(e->get_arg(l++), subst.size(), subst.c_ptr(), tmp);
|
||||
tmp = vs(e->get_arg(l++), subst.size(), subst.c_ptr());
|
||||
args.push_back(tmp);
|
||||
}
|
||||
else {
|
||||
|
@ -370,7 +370,7 @@ namespace datalog {
|
|||
}
|
||||
SASSERT(l <= new_p->get_arity());
|
||||
}
|
||||
vs(e->get_result(), subst.size(), subst.c_ptr(), res);
|
||||
res = vs(e->get_result(), subst.size(), subst.c_ptr());
|
||||
old_fi->insert_entry(args.c_ptr(), res.get());
|
||||
}
|
||||
old_model->register_decl(old_p, old_fi);
|
||||
|
|
|
@ -449,7 +449,6 @@ namespace opt {
|
|||
}
|
||||
lbool r = maxsmt();
|
||||
if (r == l_true) {
|
||||
ast_manager& m = m_solver->get_manager();
|
||||
svector<symbol> labels;
|
||||
maxsmt.get_model(m_model, labels);
|
||||
// TBD: is m_fm applied or not?
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace smt2 {
|
|||
symbol m_bang;
|
||||
symbol m_forall;
|
||||
symbol m_exists;
|
||||
symbol m_lambda;
|
||||
symbol m_as;
|
||||
symbol m_not;
|
||||
symbol m_root_obj;
|
||||
|
@ -161,7 +162,7 @@ namespace smt2 {
|
|||
};
|
||||
|
||||
struct quant_frame : public expr_frame {
|
||||
bool m_forall;
|
||||
quantifier_kind m_kind;
|
||||
symbol m_qid;
|
||||
symbol m_skid;
|
||||
unsigned m_weight;
|
||||
|
@ -170,8 +171,8 @@ namespace smt2 {
|
|||
unsigned m_sym_spos;
|
||||
unsigned m_sort_spos;
|
||||
unsigned m_expr_spos;
|
||||
quant_frame(bool forall, unsigned pat_spos, unsigned nopat_spos, unsigned sym_spos, unsigned sort_spos, unsigned expr_spos):
|
||||
expr_frame(EF_QUANT), m_forall(forall), m_weight(1),
|
||||
quant_frame(quantifier_kind k, unsigned pat_spos, unsigned nopat_spos, unsigned sym_spos, unsigned sort_spos, unsigned expr_spos):
|
||||
expr_frame(EF_QUANT), m_kind(k), m_weight(1),
|
||||
m_pat_spos(pat_spos), m_nopat_spos(nopat_spos),
|
||||
m_sym_spos(sym_spos), m_sort_spos(sort_spos),
|
||||
m_expr_spos(expr_spos) {}
|
||||
|
@ -407,6 +408,7 @@ namespace smt2 {
|
|||
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_lambda() const { SASSERT(curr_is_identifier()); return curr_id() == m_lambda; }
|
||||
bool curr_id_is_bang() const { SASSERT(curr_is_identifier()); return curr_id() == m_bang; }
|
||||
bool curr_id_is_let() const { SASSERT(curr_is_identifier()); return curr_id() == m_let; }
|
||||
bool curr_id_is_root_obj() const { SASSERT(curr_is_identifier()); return curr_id() == m_root_obj; }
|
||||
|
@ -1301,15 +1303,15 @@ namespace smt2 {
|
|||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
|
||||
void push_quant_frame(bool is_forall) {
|
||||
void push_quant_frame(quantifier_kind k) {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id_is_forall() || curr_id_is_exists());
|
||||
SASSERT(!is_forall || curr_id_is_forall());
|
||||
SASSERT(is_forall || curr_id_is_exists());
|
||||
SASSERT(curr_id_is_forall() || curr_id_is_exists() || curr_id_is_lambda());
|
||||
SASSERT((k == forall_k) == curr_id_is_forall());
|
||||
SASSERT((k == exists_k) == curr_id_is_exists());
|
||||
SASSERT((k == lambda_k) == curr_id_is_lambda());
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(quant_frame));
|
||||
new (mem) quant_frame(is_forall, pattern_stack().size(), nopattern_stack().size(), symbol_stack().size(),
|
||||
new (mem) quant_frame(k, pattern_stack().size(), nopattern_stack().size(), symbol_stack().size(),
|
||||
sort_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
unsigned num_vars = parse_sorted_vars();
|
||||
|
@ -1374,7 +1376,7 @@ namespace smt2 {
|
|||
new_case = cases[i];
|
||||
}
|
||||
else {
|
||||
sub(cases[i], subst.size(), subst.c_ptr(), new_case);
|
||||
new_case = sub(cases[i], subst.size(), subst.c_ptr());
|
||||
inv_var_shifter inv(m());
|
||||
inv(new_case, subst.size(), new_case);
|
||||
}
|
||||
|
@ -1804,7 +1806,7 @@ namespace smt2 {
|
|||
new (mem) app_frame(f, expr_spos, param_spos, has_as);
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
|
||||
void push_expr_frame(expr_frame * curr) {
|
||||
SASSERT(curr_is_lparen());
|
||||
next();
|
||||
|
@ -1815,10 +1817,13 @@ namespace smt2 {
|
|||
push_let_frame();
|
||||
}
|
||||
else if (curr_id_is_forall()) {
|
||||
push_quant_frame(true);
|
||||
push_quant_frame(forall_k);
|
||||
}
|
||||
else if (curr_id_is_exists()) {
|
||||
push_quant_frame(false);
|
||||
push_quant_frame(exists_k);
|
||||
}
|
||||
else if (curr_id_is_lambda()) {
|
||||
push_quant_frame(lambda_k);
|
||||
}
|
||||
else if (curr_id_is_bang()) {
|
||||
push_bang_frame(curr);
|
||||
|
@ -1915,6 +1920,7 @@ namespace smt2 {
|
|||
SASSERT(expr_stack().size() >= fr->m_expr_spos);
|
||||
unsigned num_decls = sort_stack().size() - fr->m_sort_spos;
|
||||
if (expr_stack().size() - fr->m_expr_spos != num_decls /* variables */ + 1 /* result */)
|
||||
//throw parser_exception("invalid quantified expression, syntax error: (forall|exists|lambda ((<symbol> <sort>)*) <expr>) expected");
|
||||
throw parser_exception("invalid quantified expression, syntax error: (forall|exists ((<symbol> <sort>)*) <expr>) expected");
|
||||
unsigned begin_pats = fr->m_pat_spos;
|
||||
unsigned end_pats = pattern_stack().size();
|
||||
|
@ -1938,19 +1944,19 @@ namespace smt2 {
|
|||
TRACE("parse_quantifier", tout << "body:\n" << mk_pp(expr_stack().back(), m()) << "\n";);
|
||||
if (fr->m_qid == symbol::null)
|
||||
fr->m_qid = symbol(m_scanner.get_line());
|
||||
if (!m().is_bool(expr_stack().back()))
|
||||
if (fr->m_kind != lambda_k && !m().is_bool(expr_stack().back()))
|
||||
throw parser_exception("quantifier body must be a Boolean expression");
|
||||
quantifier * new_q = m().mk_quantifier(fr->m_forall,
|
||||
num_decls,
|
||||
sort_stack().c_ptr() + fr->m_sort_spos,
|
||||
symbol_stack().c_ptr() + fr->m_sym_spos,
|
||||
expr_stack().back(),
|
||||
fr->m_weight,
|
||||
fr->m_qid,
|
||||
fr->m_skid,
|
||||
num_pats, pattern_stack().c_ptr() + fr->m_pat_spos,
|
||||
num_nopats, nopattern_stack().c_ptr() + fr->m_nopat_spos
|
||||
);
|
||||
quantifier* new_q = m().mk_quantifier(fr->m_kind,
|
||||
num_decls,
|
||||
sort_stack().c_ptr() + fr->m_sort_spos,
|
||||
symbol_stack().c_ptr() + fr->m_sym_spos,
|
||||
expr_stack().back(),
|
||||
fr->m_weight,
|
||||
fr->m_qid,
|
||||
fr->m_skid,
|
||||
num_pats, pattern_stack().c_ptr() + fr->m_pat_spos,
|
||||
num_nopats, nopattern_stack().c_ptr() + fr->m_nopat_spos
|
||||
);
|
||||
TRACE("mk_quantifier", tout << "id: " << new_q->get_id() << "\n" << mk_ismt2_pp(new_q, m()) << "\n";);
|
||||
TRACE("skid", tout << "new_q->skid: " << new_q->get_skid() << "\n";);
|
||||
expr_stack().shrink(fr->m_expr_spos);
|
||||
|
@ -2965,6 +2971,7 @@ namespace smt2 {
|
|||
m_bang("!"),
|
||||
m_forall("forall"),
|
||||
m_exists("exists"),
|
||||
m_lambda("lambda"),
|
||||
m_as("as"),
|
||||
m_not("not"),
|
||||
m_root_obj("root-obj"),
|
||||
|
|
|
@ -2269,8 +2269,7 @@ namespace qe {
|
|||
bound.push_back(m.mk_fresh_const("bound", fv[i]));
|
||||
}
|
||||
var_subst subst(m);
|
||||
subst(fml, bound.size(), bound.c_ptr(), tmp);
|
||||
fml = tmp;
|
||||
fml = subst(fml, bound.size(), bound.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2291,7 +2290,7 @@ namespace qe {
|
|||
}
|
||||
expr* const* exprs = (expr* const*)(vars.c_ptr());
|
||||
var_subst subst(m);
|
||||
subst(new_body, vars.size(), exprs, tmp);
|
||||
tmp = subst(new_body, vars.size(), exprs);
|
||||
inv_var_shifter shift(m);
|
||||
shift(tmp, vars.size(), new_body);
|
||||
}
|
||||
|
@ -2337,13 +2336,18 @@ namespace qe {
|
|||
case AST_QUANTIFIER: {
|
||||
app_ref_vector vars(m);
|
||||
quantifier* q = to_quantifier(e);
|
||||
bool is_fa = q->is_forall();
|
||||
tmp = q->get_expr();
|
||||
extract_vars(q, tmp, vars);
|
||||
elim(tmp);
|
||||
init_qe();
|
||||
m_qe->set_assumption(m_assumption);
|
||||
m_qe->eliminate(is_fa, vars.size(), vars.c_ptr(), tmp);
|
||||
if (is_lambda(q)) {
|
||||
tmp = e;
|
||||
}
|
||||
else {
|
||||
bool is_fa = is_forall(q);
|
||||
tmp = q->get_expr();
|
||||
extract_vars(q, tmp, vars);
|
||||
elim(tmp);
|
||||
init_qe();
|
||||
m_qe->set_assumption(m_assumption);
|
||||
m_qe->eliminate(is_fa, vars.size(), vars.c_ptr(), tmp);
|
||||
}
|
||||
m_trail.push_back(tmp);
|
||||
m_visited.insert(e, tmp);
|
||||
todo.pop_back();
|
||||
|
@ -2593,6 +2597,9 @@ namespace qe {
|
|||
)
|
||||
{
|
||||
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
// bool is_forall = old_q->is_forall();
|
||||
app_ref_vector vars(m);
|
||||
TRACE("qe", tout << "simplifying" << mk_pp(new_body, m) << "\n";);
|
||||
|
@ -2600,11 +2607,11 @@ namespace qe {
|
|||
extract_vars(old_q, result, vars);
|
||||
TRACE("qe", tout << "variables extracted" << mk_pp(result, m) << "\n";);
|
||||
|
||||
if (old_q->is_forall()) {
|
||||
if (is_forall(old_q)) {
|
||||
result = mk_not(m, result);
|
||||
}
|
||||
m_ctx.solve(result, vars);
|
||||
if (old_q->is_forall()) {
|
||||
if (is_forall(old_q)) {
|
||||
expr* e = nullptr;
|
||||
result = m.is_not(result, e)?e:mk_not(m, result);
|
||||
}
|
||||
|
@ -2619,7 +2626,7 @@ namespace qe {
|
|||
names.push_back(vars[i]->get_decl()->get_name());
|
||||
}
|
||||
if (!vars.empty()) {
|
||||
result = m.mk_quantifier(old_q->is_forall(), vars.size(), sorts.c_ptr(), names.c_ptr(), result, 1);
|
||||
result = m.mk_quantifier(old_q->get_kind(), vars.size(), sorts.c_ptr(), names.c_ptr(), result, 1);
|
||||
}
|
||||
result_pr = nullptr;
|
||||
return true;
|
||||
|
|
|
@ -327,8 +327,8 @@ namespace eq {
|
|||
|
||||
void flatten_args(quantifier* q, unsigned& num_args, expr*const*& args) {
|
||||
expr * e = q->get_expr();
|
||||
if ((q->is_forall() && m.is_or(e)) ||
|
||||
(q->is_exists() && m.is_and(e))) {
|
||||
if ((is_forall(q) && m.is_or(e)) ||
|
||||
(is_exists(q) && m.is_and(e))) {
|
||||
num_args = to_app(e)->get_num_args();
|
||||
args = to_app(e)->get_args();
|
||||
}
|
||||
|
@ -356,27 +356,29 @@ namespace eq {
|
|||
}
|
||||
|
||||
expr_ref t(m);
|
||||
if (q->is_forall()) {
|
||||
switch (q->get_kind()) {
|
||||
case forall_k:
|
||||
rw.mk_or(m_new_args.size(), m_new_args.c_ptr(), t);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case exists_k:
|
||||
rw.mk_and(m_new_args.size(), m_new_args.c_ptr(), t);
|
||||
break;
|
||||
default:
|
||||
t = e;
|
||||
break;
|
||||
}
|
||||
expr_ref new_e(m);
|
||||
m_subst(t, new_e);
|
||||
expr_ref new_e = m_subst(t, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m);
|
||||
expr_ref_buffer new_no_patterns(m);
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref new_pat(m);
|
||||
m_subst(q->get_pattern(j), new_pat);
|
||||
expr_ref new_pat = m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_patterns.push_back(new_pat);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref new_nopat(m);
|
||||
m_subst(q->get_no_pattern(j), new_nopat);
|
||||
expr_ref new_nopat = m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
|
@ -390,12 +392,17 @@ namespace eq {
|
|||
set_is_variable_proc(is_v);
|
||||
unsigned num_args = 1;
|
||||
expr* const* args = &e;
|
||||
if (is_lambda(q)) {
|
||||
r = q;
|
||||
pr = 0;
|
||||
return;
|
||||
}
|
||||
flatten_args(q, num_args, args);
|
||||
|
||||
unsigned def_count = 0;
|
||||
unsigned largest_vinx = 0;
|
||||
|
||||
find_definitions(num_args, args, q->is_exists(), def_count, largest_vinx);
|
||||
find_definitions(num_args, args, is_exists(q), def_count, largest_vinx);
|
||||
|
||||
if (def_count > 0) {
|
||||
get_elimination_order();
|
||||
|
@ -423,7 +430,7 @@ namespace eq {
|
|||
if (is_quantifier(r)) {
|
||||
quantifier * q = to_quantifier(r);
|
||||
|
||||
::elim_unused_vars(m, q, m_params, r);
|
||||
r = ::elim_unused_vars(m, q, m_params);
|
||||
if (m.proofs_enabled()) {
|
||||
proof * p1 = m.mk_elim_unused_vars(q, r);
|
||||
pr = m.mk_transitivity(pr, p1);
|
||||
|
@ -624,7 +631,7 @@ namespace eq {
|
|||
expr_ref r(m), new_r(m);
|
||||
r = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
create_substitution(largest_vinx + 1);
|
||||
m_subst(r, new_r);
|
||||
new_r = m_subst(r, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
m_rewriter(new_r);
|
||||
conjs.reset();
|
||||
flatten_and(new_r, conjs);
|
||||
|
@ -1756,16 +1763,12 @@ namespace fm {
|
|||
// x_cost_lt is not a total order on variables
|
||||
std::stable_sort(x_cost_vector.begin(), x_cost_vector.end(), x_cost_lt(m_is_int));
|
||||
TRACE("qe_lite",
|
||||
svector<x_cost>::iterator it2 = x_cost_vector.begin();
|
||||
svector<x_cost>::iterator end2 = x_cost_vector.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
tout << "(" << mk_ismt2_pp(m_var2expr.get(it2->first), m) << " " << it2->second << ") ";
|
||||
for (auto const& kv : x_cost_vector) {
|
||||
tout << "(" << mk_ismt2_pp(m_var2expr.get(kv.first), m) << " " << kv.second << ") ";
|
||||
}
|
||||
tout << "\n";);
|
||||
svector<x_cost>::iterator it2 = x_cost_vector.begin();
|
||||
svector<x_cost>::iterator end2 = x_cost_vector.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
xs.push_back(it2->first);
|
||||
for (auto const& kv : x_cost_vector) {
|
||||
xs.push_back(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1802,11 +1805,9 @@ namespace fm {
|
|||
void analyze(constraints const & cs, var x, bool & all_int, bool & unit_coeff) const {
|
||||
all_int = true;
|
||||
unit_coeff = true;
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it) {
|
||||
for (constraint const* c : cs) {
|
||||
bool curr_unit_coeff;
|
||||
analyze(*(*it), x, all_int, curr_unit_coeff);
|
||||
analyze(*c, x, all_int, curr_unit_coeff);
|
||||
if (!all_int)
|
||||
return;
|
||||
if (!curr_unit_coeff)
|
||||
|
@ -1830,10 +1831,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void copy_constraints(constraints const & s, clauses & t) {
|
||||
constraints::const_iterator it = s.begin();
|
||||
constraints::const_iterator end = s.end();
|
||||
for (; it != end; ++it) {
|
||||
app * c = to_expr(*(*it));
|
||||
for (constraint const* cns : s) {
|
||||
app * c = to_expr(*cns);
|
||||
t.push_back(c);
|
||||
}
|
||||
}
|
||||
|
@ -1842,10 +1841,8 @@ namespace fm {
|
|||
void save_constraints(var x) { }
|
||||
|
||||
void mark_constraints_dead(constraints const & cs) {
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it)
|
||||
(*it)->m_dead = true;
|
||||
for (constraint* c : cs)
|
||||
c->m_dead = true;
|
||||
}
|
||||
|
||||
void mark_constraints_dead(var x) {
|
||||
|
@ -2094,14 +2091,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void copy_remaining(vector<constraints> & v2cs) {
|
||||
vector<constraints>::iterator it = v2cs.begin();
|
||||
vector<constraints>::iterator end = v2cs.end();
|
||||
for (; it != end; ++it) {
|
||||
constraints & cs = *it;
|
||||
constraints::iterator it2 = cs.begin();
|
||||
constraints::iterator end2 = cs.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
constraint * c = *it2;
|
||||
for (constraints& cs : v2cs) {
|
||||
for (constraint* c : cs) {
|
||||
if (!c->m_dead) {
|
||||
c->m_dead = true;
|
||||
expr * new_f = to_expr(*c);
|
||||
|
@ -2170,11 +2161,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void display_constraints(std::ostream & out, constraints const & cs) const {
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it) {
|
||||
out << " ";
|
||||
display(out, *(*it));
|
||||
for (constraint const* c : cs) {
|
||||
display(out << " ", *c);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
@ -2215,7 +2203,9 @@ public:
|
|||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
indices.insert(i);
|
||||
}
|
||||
m_imp(indices, true, result);
|
||||
if (q->get_kind() != lambda_k) {
|
||||
m_imp(indices, true, result);
|
||||
}
|
||||
if (is_forall(q)) {
|
||||
result = push_not(result);
|
||||
}
|
||||
|
@ -2295,7 +2285,7 @@ public:
|
|||
tmp = to_quantifier(tmp)->get_expr();
|
||||
used.process(tmp);
|
||||
var_subst vs(m, true);
|
||||
vs(tmp, vars.size(), (expr*const*)vars.c_ptr(), fml);
|
||||
fml = vs(tmp, vars.size(), (expr*const*)vars.c_ptr());
|
||||
// collect set of variables that were used.
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
|
|
|
@ -31,6 +31,7 @@ Revision History:
|
|||
#include "qe/qe_arrays.h"
|
||||
#include "qe/qe_datatypes.h"
|
||||
#include "qe/qe_lite.h"
|
||||
#include "model/model_pp.h"
|
||||
#include "model/model_evaluator.h"
|
||||
|
||||
|
||||
|
@ -616,7 +617,7 @@ public:
|
|||
qe::array_project_plugin ap(m);
|
||||
ap(mdl, array_vars, fml, vars, m_reduce_all_selects);
|
||||
SASSERT (array_vars.empty ());
|
||||
m_rw(fml);
|
||||
m_rw (fml);
|
||||
SASSERT (!m.is_false (fml));
|
||||
|
||||
TRACE ("qe",
|
||||
|
@ -650,9 +651,9 @@ public:
|
|||
// substitute any remaining other vars
|
||||
if (!m_dont_sub && !other_vars.empty ()) {
|
||||
subst_vars (eval, other_vars, fml);
|
||||
TRACE ("qe", tout << "After substituting remaining other vars:\n" << fml << "\n";);
|
||||
// an extra round of simplification because subst_vars is not simplifying
|
||||
m_rw(fml);
|
||||
TRACE ("qe", tout << "After substituting remaining other vars:\n" << fml << "\n";);
|
||||
other_vars.reset();
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue