diff --git a/src/api/api_datalog.cpp b/src/api/api_datalog.cpp
index 7674e8676..52cdeaec9 100644
--- a/src/api/api_datalog.cpp
+++ b/src/api/api_datalog.cpp
@@ -449,6 +449,23 @@ extern "C" {
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
+
+ Z3_ast_vector Z3_API Z3_fixedpoint_get_assertions(
+ Z3_context c,
+ Z3_fixedpoint d)
+ {
+ Z3_TRY;
+ LOG_Z3_fixedpoint_get_assertions(c, d);
+ ast_manager& m = mk_c(c)->m();
+ Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, m);
+ mk_c(c)->save_object(v);
+ unsigned num_asserts = to_fixedpoint_ref(d)->ctx().get_num_assertions();
+ for (unsigned i = 0; i < num_asserts; ++i) {
+ v->m_ast_vector.push_back(to_fixedpoint_ref(d)->ctx().get_assertion(i));
+ }
+ RETURN_Z3(of_ast_vector(v));
+ Z3_CATCH_RETURN(0);
+ }
void Z3_API Z3_fixedpoint_set_reduce_assign_callback(
Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_assign_callback_fptr f) {
diff --git a/src/api/dotnet/Fixedpoint.cs b/src/api/dotnet/Fixedpoint.cs
index c8a677196..aca013318 100644
--- a/src/api/dotnet/Fixedpoint.cs
+++ b/src/api/dotnet/Fixedpoint.cs
@@ -278,6 +278,23 @@ namespace Microsoft.Z3
}
}
+ ///
+ /// Retrieve set of assertions added to fixedpoint context.
+ ///
+ public BoolExpr[] Assertions {
+ get
+ {
+ Contract.Ensures(Contract.Result() != null);
+
+ ASTVector v = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
+ uint n = v.Size;
+ BoolExpr[] res = new BoolExpr[n];
+ for (uint i = 0; i < n; i++)
+ res[i] = new BoolExpr(Context, v[i].NativeObject);
+ return res;
+ }
+ }
+
#region Internal
internal Fixedpoint(Context ctx, IntPtr obj)
diff --git a/src/api/python/z3.py b/src/api/python/z3.py
index 3e73e9b1a..21666f569 100644
--- a/src/api/python/z3.py
+++ b/src/api/python/z3.py
@@ -6145,7 +6145,11 @@ class Fixedpoint(Z3PPObject):
def get_rules(self):
"""retrieve rules that have been added to fixedpoint context"""
return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx)
-
+
+ def get_assertions(self):
+ """retrieve assertions that have been added to fixedpoint context"""
+ return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx)
+
def __repr__(self):
"""Return a formatted string with all added rules and constraints."""
return self.sexpr()
diff --git a/src/api/z3_api.h b/src/api/z3_api.h
index 5fa296ff6..7c9247459 100644
--- a/src/api/z3_api.h
+++ b/src/api/z3_api.h
@@ -5696,6 +5696,15 @@ END_MLAPI_EXCLUDE
__in Z3_context c,
__in Z3_fixedpoint f);
+ /**
+ \brief Retrieve set of background assertions from fixedpoint context.
+
+ def_API('Z3_fixedpoint_get_assertions', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT)))
+ */
+ Z3_ast_vector Z3_API Z3_fixedpoint_get_assertions(
+ __in Z3_context c,
+ __in Z3_fixedpoint f);
+
/**
\brief Set parameters on fixedpoint context.
diff --git a/src/muz_qe/dl_cmds.cpp b/src/muz_qe/dl_cmds.cpp
index a4bc4de6d..e19b9fef8 100644
--- a/src/muz_qe/dl_cmds.cpp
+++ b/src/muz_qe/dl_cmds.cpp
@@ -315,7 +315,7 @@ private:
if (m_params.get_bool(":print-certificate", false)) {
datalog::context& dlctx = m_dl_ctx->dlctx();
if (!dlctx.display_certificate(ctx.regular_stream())) {
- throw cmd_exception("certificates are not supported for selected DL_ENGINE");
+ throw cmd_exception("certificates are not supported for the selected engine");
}
ctx.regular_stream() << "\n";
}
diff --git a/src/muz_qe/dl_context.cpp b/src/muz_qe/dl_context.cpp
index 13008d059..9a5f7280c 100644
--- a/src/muz_qe/dl_context.cpp
+++ b/src/muz_qe/dl_context.cpp
@@ -238,6 +238,7 @@ namespace datalog {
m_pinned(m),
m_vars(m),
m_rule_set(*this),
+ m_rule_fmls(m),
m_background(m),
m_closed(false),
m_saturation_was_run(false),
@@ -521,10 +522,19 @@ namespace datalog {
}
void context::add_rule(expr* rl, symbol const& name) {
+ m_rule_fmls.push_back(rl);
+ m_rule_names.push_back(name);
+ }
+
+ void context::flush_add_rules() {
datalog::rule_manager& rm = get_rule_manager();
datalog::rule_ref_vector rules(rm);
- rm.mk_rule(rl, rules, name);
+ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
+ rm.mk_rule(m_rule_fmls[i].get(), rules, m_rule_names[i]);
+ }
add_rules(rules);
+ m_rule_fmls.reset();
+ m_rule_names.reset();
}
//
@@ -1223,6 +1233,7 @@ namespace datalog {
}
void context::new_query() {
+ flush_add_rules();
if (m_last_result_relation) {
m_last_result_relation->deallocate();
m_last_result_relation = 0;
@@ -1512,7 +1523,7 @@ namespace datalog {
switch(get_engine()) {
case DATALOG_ENGINE:
return false;
- case PDR_ENGINE:
+ case QPDR_ENGINE:
ensure_pdr();
m_pdr->display_certificate(out);
return true;
@@ -1618,6 +1629,10 @@ namespace datalog {
names.push_back((*it)->name());
}
}
+ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
+ rules.push_back(m_rule_fmls[i].get());
+ names.push_back(m_rule_names[i]);
+ }
smt2_pp_environment_dbg env(m);
pp_params params;
@@ -1674,8 +1689,11 @@ namespace datalog {
declare_vars(rules, fresh_names, out);
}
+ if (num_axioms > 0 && !use_fixedpoint_extensions) {
+ throw default_exception("Background axioms cannot be used with SMT-LIB2 HORN format");
+ }
+
for (unsigned i = 0; i < num_axioms; ++i) {
- SASSERT(use_fixedpoint_extensions);
out << "(assert ";
ast_smt2_pp(out, axioms[i], env, params);
out << ")\n";
diff --git a/src/muz_qe/dl_context.h b/src/muz_qe/dl_context.h
index a6f8fc5e2..3818052e2 100644
--- a/src/muz_qe/dl_context.h
+++ b/src/muz_qe/dl_context.h
@@ -96,6 +96,8 @@ namespace datalog {
pred2syms m_argument_var_names;
decl_set m_output_preds;
rule_set m_rule_set;
+ expr_ref_vector m_rule_fmls;
+ svector m_rule_names;
expr_ref_vector m_background;
scoped_ptr m_pdr;
@@ -259,6 +261,8 @@ namespace datalog {
void assert_expr(expr* e);
expr_ref get_background_assertion();
+ unsigned get_num_assertions() { return m_background.size(); }
+ expr* get_assertion(unsigned i) const { return m_background[i]; }
/**
Method exposed from API for adding rules.
@@ -454,6 +458,8 @@ namespace datalog {
private:
+ void flush_add_rules();
+
void ensure_pdr();
void ensure_bmc();
diff --git a/src/muz_qe/dl_mk_rule_inliner.cpp b/src/muz_qe/dl_mk_rule_inliner.cpp
index f92a56a4f..1d3d62020 100644
--- a/src/muz_qe/dl_mk_rule_inliner.cpp
+++ b/src/muz_qe/dl_mk_rule_inliner.cpp
@@ -194,6 +194,7 @@ namespace datalog {
}
}
+ // TBD: replace by r.has_quantifiers() and test
bool mk_rule_inliner::has_quantifier(rule const& r) const {
unsigned utsz = r.get_uninterpreted_tail_size();
for (unsigned i = utsz; i < r.get_tail_size(); ++i) {
diff --git a/src/muz_qe/dl_mk_slice.cpp b/src/muz_qe/dl_mk_slice.cpp
index 1f1d12340..2ff341e07 100644
--- a/src/muz_qe/dl_mk_slice.cpp
+++ b/src/muz_qe/dl_mk_slice.cpp
@@ -818,6 +818,11 @@ namespace datalog {
}
rule_set * mk_slice::operator()(rule_set const & src, model_converter_ref& mc, proof_converter_ref& pc) {
+ for (unsigned i = 0; i < src.get_num_rules(); ++i) {
+ if (src.get_rule(i)->has_quantifiers()) {
+ return 0;
+ }
+ }
ref spc;
ref smc;
if (pc) {