mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
merge with unstable
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
23e811d136
95 changed files with 24076 additions and 414 deletions
|
@ -179,6 +179,7 @@ namespace datalog {
|
|||
void context::push() {
|
||||
m_trail.push_scope();
|
||||
m_trail.push(restore_rules(m_rule_set));
|
||||
m_trail.push(restore_vec_size_trail<context,expr_ref_vector>(m_rule_fmls));
|
||||
m_trail.push(restore_vec_size_trail<context,expr_ref_vector>(m_background));
|
||||
}
|
||||
|
||||
|
@ -186,6 +187,10 @@ namespace datalog {
|
|||
if (m_trail.get_num_scopes() == 0) {
|
||||
throw default_exception("there are no backtracking points to pop to");
|
||||
}
|
||||
if(m_engine.get()){
|
||||
if(get_engine() != DUALITY_ENGINE)
|
||||
throw default_exception("operation is not supported by engine");
|
||||
}
|
||||
m_trail.pop_scope(1);
|
||||
}
|
||||
|
||||
|
@ -699,6 +704,10 @@ namespace datalog {
|
|||
check_existential_tail(r);
|
||||
check_positive_predicates(r);
|
||||
break;
|
||||
case DUALITY_ENGINE:
|
||||
check_existential_tail(r);
|
||||
check_positive_predicates(r);
|
||||
break;
|
||||
case CLP_ENGINE:
|
||||
check_existential_tail(r);
|
||||
check_positive_predicates(r);
|
||||
|
@ -920,6 +929,9 @@ namespace datalog {
|
|||
else if (e == symbol("clp")) {
|
||||
m_engine_type = CLP_ENGINE;
|
||||
}
|
||||
else if (e == symbol("duality")) {
|
||||
m_engine_type = DUALITY_ENGINE;
|
||||
}
|
||||
|
||||
if (m_engine_type == LAST_ENGINE) {
|
||||
expr_fast_mark1 mark;
|
||||
|
@ -945,6 +957,18 @@ namespace datalog {
|
|||
}
|
||||
|
||||
lbool context::query(expr* query) {
|
||||
#if 0
|
||||
// TODO: what?
|
||||
if(get_engine() != DUALITY_ENGINE) {
|
||||
new_query();
|
||||
rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
|
||||
rule_ref r(m_rule_manager);
|
||||
for (; it != end; ++it) {
|
||||
r = *it;
|
||||
check_rule(r);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_mc = mk_skip_model_converter();
|
||||
m_last_status = OK;
|
||||
m_last_answer = 0;
|
||||
|
@ -958,6 +982,8 @@ namespace datalog {
|
|||
case CLP_ENGINE:
|
||||
flush_add_rules();
|
||||
break;
|
||||
case DUALITY_ENGINE:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -983,6 +1009,7 @@ namespace datalog {
|
|||
if (get_engine() == DATALOG_ENGINE) {
|
||||
m_rel = dynamic_cast<rel_context_base*>(m_engine.get());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,7 +1041,6 @@ namespace datalog {
|
|||
out << "\n---------------\n";
|
||||
out << "Original rules\n";
|
||||
display_rules(out);
|
||||
|
||||
out << "\n---------------\n";
|
||||
out << "Transformed rules\n";
|
||||
m_transformed_rule_set.display(out);
|
||||
|
@ -1076,6 +1102,15 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void context::get_raw_rule_formulas(expr_ref_vector& rules, svector<symbol>& names){
|
||||
for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
|
||||
expr_ref r = bind_variables(m_rule_fmls[i].get(), true);
|
||||
rules.push_back(r.get());
|
||||
// rules.push_back(m_rule_fmls[i].get());
|
||||
names.push_back(m_rule_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void context::get_rules_as_formulas(expr_ref_vector& rules, svector<symbol>& names) {
|
||||
expr_ref fml(m);
|
||||
datalog::rule_manager& rm = get_rule_manager();
|
||||
|
|
|
@ -357,6 +357,7 @@ namespace datalog {
|
|||
rule_set & get_rules() { flush_add_rules(); return m_rule_set; }
|
||||
|
||||
void get_rules_as_formulas(expr_ref_vector& fmls, svector<symbol>& names);
|
||||
void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names);
|
||||
|
||||
void add_fact(app * head);
|
||||
void add_fact(func_decl * pred, const relation_fact & fact);
|
||||
|
@ -492,14 +493,16 @@ namespace datalog {
|
|||
/**
|
||||
\brief retrieve model from inductive invariant that shows query is unsat.
|
||||
|
||||
\pre engine == 'pdr' - this option is only supported for PDR mode.
|
||||
\pre engine == 'pdr' || engine == 'duality' - this option is only supported
|
||||
for PDR mode and Duality mode.
|
||||
*/
|
||||
model_ref get_model();
|
||||
|
||||
/**
|
||||
\brief retrieve proof from derivation of the query.
|
||||
|
||||
\pre engine == 'pdr' - this option is only supported for PDR mode.
|
||||
\pre engine == 'pdr' || engine == 'duality'- this option is only supported
|
||||
for PDR mode and Duality mode.
|
||||
*/
|
||||
proof_ref get_proof();
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace datalog {
|
|||
QBMC_ENGINE,
|
||||
TAB_ENGINE,
|
||||
CLP_ENGINE,
|
||||
LAST_ENGINE
|
||||
LAST_ENGINE,
|
||||
DUALITY_ENGINE
|
||||
};
|
||||
|
||||
class engine_base {
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace datalog {
|
|||
LAST_CACHE_MODE
|
||||
};
|
||||
|
||||
|
||||
struct std_string_hash_proc {
|
||||
unsigned operator()(const std::string & s) const
|
||||
{ return string_hash(s.c_str(), static_cast<unsigned>(s.length()), 17); }
|
||||
|
|
|
@ -67,6 +67,13 @@ def_module_params('fixedpoint',
|
|||
('print_statistics', BOOL, False, 'print statistics'),
|
||||
('use_utvpi', BOOL, True, 'PDR: Enable UTVPI strategy'),
|
||||
('tab_selection', SYMBOL, 'weight', 'selection method for tabular strategy: weight (default), first, var-use'),
|
||||
('full_expand', BOOL, False, 'DUALITY: Fully expand derivation trees'),
|
||||
('no_conj', BOOL, False, 'DUALITY: No forced covering (conjectures)'),
|
||||
('feasible_edges', BOOL, True, 'DUALITY: Don\'t expand definitley infeasible edges'),
|
||||
('use_underapprox', BOOL, False, 'DUALITY: Use underapproximations'),
|
||||
('stratified_inlining', BOOL, False, 'DUALITY: Use stratified inlining'),
|
||||
('recursion_bound', UINT, UINT_MAX, 'DUALITY: Recursion bound for stratified inlining'),
|
||||
('profile', BOOL, False, 'DUALITY: profile run time'),
|
||||
('dump_aig', SYMBOL, '', 'Dump clauses in AIG text format (AAG) to the given file name'),
|
||||
))
|
||||
|
||||
|
|
493
src/muz/duality/duality_dl_interface.cpp
Normal file
493
src/muz/duality/duality_dl_interface.cpp
Normal file
|
@ -0,0 +1,493 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
duality_dl_interface.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
SMT2 interface for Duality
|
||||
|
||||
Author:
|
||||
|
||||
Krystof Hoder (t-khoder) 2011-9-22.
|
||||
Modified by Ken McMIllan (kenmcmil) 2013-4-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "dl_context.h"
|
||||
#include "dl_mk_coi_filter.h"
|
||||
#include "dl_mk_interp_tail_simplifier.h"
|
||||
#include "dl_mk_subsumption_checker.h"
|
||||
#include "dl_mk_rule_inliner.h"
|
||||
#include "dl_rule.h"
|
||||
#include "dl_rule_transformer.h"
|
||||
#include "smt2parser.h"
|
||||
#include "duality_dl_interface.h"
|
||||
#include "dl_rule_set.h"
|
||||
#include "dl_mk_slice.h"
|
||||
#include "dl_mk_unfold.h"
|
||||
#include "dl_mk_coalesce.h"
|
||||
#include "expr_abstract.h"
|
||||
#include "model_smt2_pp.h"
|
||||
#include "model_v2_pp.h"
|
||||
#include "fixedpoint_params.hpp"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
// template class symbol_table<family_id>;
|
||||
|
||||
|
||||
#include "duality.h"
|
||||
#include "duality_profiling.h"
|
||||
|
||||
// using namespace Duality;
|
||||
|
||||
namespace Duality {
|
||||
|
||||
enum DualityStatus {StatusModel, StatusRefutation, StatusUnknown, StatusNull};
|
||||
|
||||
class duality_data {
|
||||
public:
|
||||
context ctx;
|
||||
RPFP::LogicSolver *ls;
|
||||
RPFP *rpfp;
|
||||
|
||||
DualityStatus status;
|
||||
std::vector<expr> clauses;
|
||||
std::vector<std::vector<RPFP::label_struct> > clause_labels;
|
||||
hash_map<RPFP::Edge *,int> map; // edges to clauses
|
||||
Solver::Counterexample cex;
|
||||
|
||||
duality_data(ast_manager &_m) : ctx(_m,config(params_ref())) {
|
||||
ls = 0;
|
||||
rpfp = 0;
|
||||
status = StatusNull;
|
||||
}
|
||||
~duality_data(){
|
||||
if(rpfp)
|
||||
dealloc(rpfp);
|
||||
if(ls)
|
||||
dealloc(ls);
|
||||
if(cex.tree)
|
||||
delete cex.tree;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
dl_interface::dl_interface(datalog::context& dl_ctx) :
|
||||
engine_base(dl_ctx.get_manager(), "duality"),
|
||||
m_ctx(dl_ctx)
|
||||
|
||||
{
|
||||
_d = 0;
|
||||
// dl_ctx.get_manager().toggle_proof_mode(PGM_FINE);
|
||||
}
|
||||
|
||||
|
||||
dl_interface::~dl_interface() {
|
||||
if(_d)
|
||||
dealloc(_d);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Check if the new rules are weaker so that we can
|
||||
// re-use existing context.
|
||||
//
|
||||
#if 0
|
||||
void dl_interface::check_reset() {
|
||||
// TODO
|
||||
datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules();
|
||||
datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules();
|
||||
bool is_subsumed = !old_rules.empty();
|
||||
for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) {
|
||||
is_subsumed = false;
|
||||
for (unsigned j = 0; !is_subsumed && j < old_rules.size(); ++j) {
|
||||
if (m_ctx.check_subsumes(*old_rules[j], *new_rules[i])) {
|
||||
is_subsumed = true;
|
||||
}
|
||||
}
|
||||
if (!is_subsumed) {
|
||||
TRACE("pdr", new_rules[i]->display(m_ctx, tout << "Fresh rule "););
|
||||
m_context->reset();
|
||||
}
|
||||
}
|
||||
m_old_rules.reset();
|
||||
m_old_rules.add_rules(new_rules.size(), new_rules.c_ptr());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
lbool dl_interface::query(::expr * query) {
|
||||
|
||||
// we restore the initial state in the datalog context
|
||||
m_ctx.ensure_opened();
|
||||
|
||||
// if there is old data, get the cex and dispose (later)
|
||||
Solver::Counterexample old_cex;
|
||||
duality_data *old_data = _d;
|
||||
if(old_data)
|
||||
old_cex = old_data->cex;
|
||||
|
||||
scoped_proof generate_proofs_please(m_ctx.get_manager());
|
||||
|
||||
// make a new problem and solver
|
||||
_d = alloc(duality_data,m_ctx.get_manager());
|
||||
_d->ls = alloc(RPFP::iZ3LogicSolver,_d->ctx);
|
||||
_d->rpfp = alloc(RPFP,_d->ls);
|
||||
|
||||
|
||||
|
||||
expr_ref_vector rules(m_ctx.get_manager());
|
||||
svector< ::symbol> names;
|
||||
// m_ctx.get_rules_as_formulas(rules, names);
|
||||
m_ctx.get_raw_rule_formulas(rules, names);
|
||||
|
||||
// get all the rules as clauses
|
||||
std::vector<expr> &clauses = _d->clauses;
|
||||
clauses.clear();
|
||||
for (unsigned i = 0; i < rules.size(); ++i) {
|
||||
expr e(_d->ctx,rules[i].get());
|
||||
clauses.push_back(e);
|
||||
}
|
||||
|
||||
// turn the query into a clause
|
||||
expr q(_d->ctx,m_ctx.bind_variables(query,false));
|
||||
|
||||
std::vector<sort> b_sorts;
|
||||
std::vector<symbol> b_names;
|
||||
if (q.is_quantifier() && !q.is_quantifier_forall()) {
|
||||
int bound = q.get_quantifier_num_bound();
|
||||
for(int j = 0; j < bound; j++){
|
||||
b_sorts.push_back(q.get_quantifier_bound_sort(j));
|
||||
b_names.push_back(q.get_quantifier_bound_name(j));
|
||||
}
|
||||
q = q.arg(0);
|
||||
}
|
||||
|
||||
expr qc = implies(q,_d->ctx.bool_val(false));
|
||||
qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc);
|
||||
clauses.push_back(qc);
|
||||
|
||||
// get the background axioms
|
||||
unsigned num_asserts = m_ctx.get_num_assertions();
|
||||
for (unsigned i = 0; i < num_asserts; ++i) {
|
||||
expr e(_d->ctx,m_ctx.get_assertion(i));
|
||||
_d->rpfp->AssertAxiom(e);
|
||||
}
|
||||
|
||||
// creates 1-1 map between clauses and rpfp edges
|
||||
_d->rpfp->FromClauses(clauses);
|
||||
|
||||
// populate the edge-to-clause map
|
||||
for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i)
|
||||
_d->map[_d->rpfp->edges[i]] = i;
|
||||
|
||||
// create a solver object
|
||||
|
||||
Solver *rs = Solver::Create("duality", _d->rpfp);
|
||||
|
||||
rs->LearnFrom(old_cex); // new solver gets hints from old cex
|
||||
|
||||
// set its options
|
||||
IF_VERBOSE(1, rs->SetOption("report","1"););
|
||||
rs->SetOption("full_expand",m_ctx.get_params().full_expand() ? "1" : "0");
|
||||
rs->SetOption("no_conj",m_ctx.get_params().no_conj() ? "1" : "0");
|
||||
rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0");
|
||||
rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0");
|
||||
rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0");
|
||||
unsigned rb = m_ctx.get_params().recursion_bound();
|
||||
if(rb != UINT_MAX){
|
||||
std::ostringstream os; os << rb;
|
||||
rs->SetOption("recursion_bound", os.str());
|
||||
}
|
||||
|
||||
// Solve!
|
||||
bool ans;
|
||||
try {
|
||||
ans = rs->Solve();
|
||||
}
|
||||
catch (Duality::solver::cancel_exception &exn){
|
||||
throw default_exception("duality canceled");
|
||||
}
|
||||
|
||||
// profile!
|
||||
|
||||
if(m_ctx.get_params().profile())
|
||||
print_profile(std::cout);
|
||||
|
||||
// save the result and counterexample if there is one
|
||||
_d->status = ans ? StatusModel : StatusRefutation;
|
||||
_d->cex = rs->GetCounterexample();
|
||||
|
||||
if(old_data){
|
||||
old_data->cex.tree = 0; // we own it now
|
||||
dealloc(old_data);
|
||||
}
|
||||
|
||||
|
||||
dealloc(rs);
|
||||
|
||||
// true means the RPFP problem is SAT, so the query is UNSAT
|
||||
return ans ? l_false : l_true;
|
||||
}
|
||||
|
||||
expr_ref dl_interface::get_cover_delta(int level, ::func_decl* pred_orig) {
|
||||
SASSERT(false);
|
||||
return expr_ref(m_ctx.get_manager());
|
||||
}
|
||||
|
||||
void dl_interface::add_cover(int level, ::func_decl* pred, ::expr* property) {
|
||||
SASSERT(false);
|
||||
}
|
||||
|
||||
unsigned dl_interface::get_num_levels(::func_decl* pred) {
|
||||
SASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dl_interface::collect_statistics(::statistics& st) const {
|
||||
}
|
||||
|
||||
void dl_interface::reset_statistics() {
|
||||
}
|
||||
|
||||
static hash_set<func_decl> *local_func_decls;
|
||||
|
||||
static void print_proof(dl_interface *d, std::ostream& out, Solver::Counterexample &cex) {
|
||||
context &ctx = d->dd()->ctx;
|
||||
RPFP::Node &node = *cex.root;
|
||||
RPFP::Edge &edge = *node.Outgoing;
|
||||
|
||||
// first, prove the children (that are actually used)
|
||||
|
||||
for(unsigned i = 0; i < edge.Children.size(); i++){
|
||||
if(!cex.tree->Empty(edge.Children[i])){
|
||||
Solver::Counterexample foo = cex;
|
||||
foo.root = edge.Children[i];
|
||||
print_proof(d,out,foo);
|
||||
}
|
||||
}
|
||||
|
||||
// print the label and the proved fact
|
||||
|
||||
out << "(step s!" << node.number;
|
||||
out << " (" << node.Name.name();
|
||||
for(unsigned i = 0; i < edge.F.IndParams.size(); i++)
|
||||
out << " " << cex.tree->Eval(&edge,edge.F.IndParams[i]);
|
||||
out << ")\n";
|
||||
|
||||
// print the rule number
|
||||
|
||||
out << " rule!" << node.Outgoing->map->number;
|
||||
|
||||
// print the substitution
|
||||
|
||||
out << " (subst\n";
|
||||
RPFP::Edge *orig_edge = edge.map;
|
||||
int orig_clause = d->dd()->map[orig_edge];
|
||||
expr &t = d->dd()->clauses[orig_clause];
|
||||
if (t.is_quantifier() && t.is_quantifier_forall()) {
|
||||
int bound = t.get_quantifier_num_bound();
|
||||
std::vector<sort> sorts;
|
||||
std::vector<symbol> names;
|
||||
hash_map<int,expr> subst;
|
||||
for(int j = 0; j < bound; j++){
|
||||
sort the_sort = t.get_quantifier_bound_sort(j);
|
||||
symbol name = t.get_quantifier_bound_name(j);
|
||||
expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort));
|
||||
out << " (= " << skolem << " " << cex.tree->Eval(&edge,skolem) << ")\n";
|
||||
expr local_skolem = cex.tree->Localize(&edge,skolem);
|
||||
(*local_func_decls).insert(local_skolem.decl());
|
||||
}
|
||||
}
|
||||
out << " )\n";
|
||||
|
||||
out << " (labels";
|
||||
std::vector<symbol> labels;
|
||||
cex.tree->GetLabels(&edge,labels);
|
||||
for(unsigned j = 0; j < labels.size(); j++){
|
||||
out << " " << labels[j];
|
||||
}
|
||||
|
||||
out << " )\n";
|
||||
|
||||
// reference the proofs of all the children, in syntactic order
|
||||
// "true" means the child is not needed
|
||||
|
||||
out << " (ref ";
|
||||
for(unsigned i = 0; i < edge.Children.size(); i++){
|
||||
if(!cex.tree->Empty(edge.Children[i]))
|
||||
out << " s!" << edge.Children[i]->number;
|
||||
else
|
||||
out << " true";
|
||||
}
|
||||
out << " )";
|
||||
out << ")\n";
|
||||
}
|
||||
|
||||
|
||||
void dl_interface::display_certificate(std::ostream& out) const {
|
||||
((dl_interface *)this)->display_certificate_non_const(out);
|
||||
}
|
||||
|
||||
void dl_interface::display_certificate_non_const(std::ostream& out) {
|
||||
if(_d->status == StatusModel){
|
||||
ast_manager &m = m_ctx.get_manager();
|
||||
model_ref md = get_model();
|
||||
model_smt2_pp(out, m, *md.get(), 0);
|
||||
}
|
||||
else if(_d->status == StatusRefutation){
|
||||
out << "(derivation\n";
|
||||
// negation of the query is the last clause -- prove it
|
||||
hash_set<func_decl> locals;
|
||||
local_func_decls = &locals;
|
||||
print_proof(this,out,_d->cex);
|
||||
out << ")\n";
|
||||
out << "(model \n\"";
|
||||
::model mod(m_ctx.get_manager());
|
||||
model orig_model = _d->cex.tree->dualModel;
|
||||
for(unsigned i = 0; i < orig_model.num_consts(); i++){
|
||||
func_decl cnst = orig_model.get_const_decl(i);
|
||||
if(locals.find(cnst) == locals.end()){
|
||||
expr thing = orig_model.get_const_interp(cnst);
|
||||
mod.register_decl(to_func_decl(cnst.raw()),to_expr(thing.raw()));
|
||||
}
|
||||
}
|
||||
for(unsigned i = 0; i < orig_model.num_funcs(); i++){
|
||||
func_decl cnst = orig_model.get_func_decl(i);
|
||||
if(locals.find(cnst) == locals.end()){
|
||||
func_interp thing = orig_model.get_func_interp(cnst);
|
||||
::func_interp *thing_raw = thing;
|
||||
mod.register_decl(to_func_decl(cnst.raw()),thing_raw->copy());
|
||||
}
|
||||
}
|
||||
model_v2_pp(out,mod);
|
||||
out << "\")\n";
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref dl_interface::get_answer() {
|
||||
SASSERT(false);
|
||||
return expr_ref(m_ctx.get_manager());
|
||||
}
|
||||
|
||||
void dl_interface::cancel() {
|
||||
#if 0
|
||||
if(_d && _d->ls)
|
||||
_d->ls->cancel();
|
||||
#else
|
||||
// HACK: duality can't cancel at all times, we just exit here
|
||||
std::cout << "(error \"duality canceled\")\nunknown\n";
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void dl_interface::cleanup() {
|
||||
}
|
||||
|
||||
void dl_interface::updt_params() {
|
||||
}
|
||||
|
||||
model_ref dl_interface::get_model() {
|
||||
ast_manager &m = m_ctx.get_manager();
|
||||
model_ref md(alloc(::model, m));
|
||||
std::vector<RPFP::Node *> &nodes = _d->rpfp->nodes;
|
||||
expr_ref_vector conjs(m);
|
||||
for (unsigned i = 0; i < nodes.size(); ++i) {
|
||||
RPFP::Node *node = nodes[i];
|
||||
func_decl &pred = node->Name;
|
||||
expr_ref prop(m);
|
||||
prop = to_expr(node->Annotation.Formula);
|
||||
std::vector<expr> ¶ms = node->Annotation.IndParams;
|
||||
expr_ref q(m);
|
||||
expr_ref_vector sig_vars(m);
|
||||
for (unsigned j = 0; j < params.size(); ++j)
|
||||
sig_vars.push_back(params[params.size()-j-1]); // TODO: why backwards?
|
||||
expr_abstract(m, 0, sig_vars.size(), sig_vars.c_ptr(), prop, q);
|
||||
if (params.empty()) {
|
||||
md->register_decl(pred, q);
|
||||
}
|
||||
else {
|
||||
::func_interp* fi = alloc(::func_interp, m, params.size());
|
||||
fi->set_else(q);
|
||||
md->register_decl(pred, fi);
|
||||
}
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
static proof_ref extract_proof(dl_interface *d, Solver::Counterexample &cex) {
|
||||
context &ctx = d->dd()->ctx;
|
||||
ast_manager &mgr = ctx.m();
|
||||
RPFP::Node &node = *cex.root;
|
||||
RPFP::Edge &edge = *node.Outgoing;
|
||||
RPFP::Edge *orig_edge = edge.map;
|
||||
|
||||
// first, prove the children (that are actually used)
|
||||
|
||||
proof_ref_vector prems(mgr);
|
||||
::vector<expr_ref_vector> substs;
|
||||
int orig_clause = d->dd()->map[orig_edge];
|
||||
expr &t = d->dd()->clauses[orig_clause];
|
||||
prems.push_back(mgr.mk_asserted(ctx.uncook(t)));
|
||||
|
||||
substs.push_back(expr_ref_vector(mgr));
|
||||
if (t.is_quantifier() && t.is_quantifier_forall()) {
|
||||
int bound = t.get_quantifier_num_bound();
|
||||
std::vector<sort> sorts;
|
||||
std::vector<symbol> names;
|
||||
hash_map<int,expr> subst;
|
||||
for(int j = 0; j < bound; j++){
|
||||
sort the_sort = t.get_quantifier_bound_sort(j);
|
||||
symbol name = t.get_quantifier_bound_name(j);
|
||||
expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort));
|
||||
expr val = cex.tree->Eval(&edge,skolem);
|
||||
expr_ref thing(ctx.uncook(val),mgr);
|
||||
substs[0].push_back(thing);
|
||||
expr local_skolem = cex.tree->Localize(&edge,skolem);
|
||||
(*local_func_decls).insert(local_skolem.decl());
|
||||
}
|
||||
}
|
||||
|
||||
svector<std::pair<unsigned, unsigned> > pos;
|
||||
for(unsigned i = 0; i < edge.Children.size(); i++){
|
||||
if(!cex.tree->Empty(edge.Children[i])){
|
||||
pos.push_back(std::pair<unsigned,unsigned>(i+1,0));
|
||||
Solver::Counterexample foo = cex;
|
||||
foo.root = edge.Children[i];
|
||||
proof_ref prem = extract_proof(d,foo);
|
||||
prems.push_back(prem);
|
||||
substs.push_back(expr_ref_vector(mgr));
|
||||
}
|
||||
}
|
||||
|
||||
func_decl f = node.Name;
|
||||
std::vector<expr> args;
|
||||
for(unsigned i = 0; i < edge.F.IndParams.size(); i++)
|
||||
args.push_back(cex.tree->Eval(&edge,edge.F.IndParams[i]));
|
||||
expr conc = f(args);
|
||||
|
||||
|
||||
::vector< ::proof *> pprems;
|
||||
for(unsigned i = 0; i < prems.size(); i++)
|
||||
pprems.push_back(prems[i].get());
|
||||
|
||||
proof_ref res(mgr.mk_hyper_resolve(pprems.size(),&pprems[0], ctx.uncook(conc), pos, substs),mgr);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
proof_ref dl_interface::get_proof() {
|
||||
if(_d->status == StatusRefutation){
|
||||
hash_set<func_decl> locals;
|
||||
local_func_decls = &locals;
|
||||
return extract_proof(this,_d->cex);
|
||||
}
|
||||
else
|
||||
return proof_ref(m_ctx.get_manager());
|
||||
}
|
||||
}
|
80
src/muz/duality/duality_dl_interface.h
Normal file
80
src/muz/duality/duality_dl_interface.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
duality_dl_interface.h
|
||||
|
||||
Abstract:
|
||||
|
||||
SMT2 interface for Duality
|
||||
|
||||
Author:
|
||||
|
||||
Krystof Hoder (t-khoder) 2011-9-22.
|
||||
Modified by Ken McMIllan (kenmcmil) 2013-4-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _DUALITY_DL_INTERFACE_H_
|
||||
#define _DUALITY_DL_INTERFACE_H_
|
||||
|
||||
#include "lbool.h"
|
||||
#include "dl_rule.h"
|
||||
#include "dl_rule_set.h"
|
||||
#include "dl_engine_base.h"
|
||||
#include "statistics.h"
|
||||
|
||||
namespace datalog {
|
||||
class context;
|
||||
}
|
||||
|
||||
namespace Duality {
|
||||
|
||||
class duality_data;
|
||||
|
||||
class dl_interface : public datalog::engine_base {
|
||||
duality_data *_d;
|
||||
datalog::context &m_ctx;
|
||||
|
||||
public:
|
||||
dl_interface(datalog::context& ctx);
|
||||
~dl_interface();
|
||||
|
||||
lbool query(expr* query);
|
||||
|
||||
void cancel();
|
||||
|
||||
void cleanup();
|
||||
|
||||
void display_certificate(std::ostream& out) const;
|
||||
|
||||
void collect_statistics(statistics& st) const;
|
||||
|
||||
void reset_statistics();
|
||||
|
||||
expr_ref get_answer();
|
||||
|
||||
unsigned get_num_levels(func_decl* pred);
|
||||
|
||||
expr_ref get_cover_delta(int level, func_decl* pred);
|
||||
|
||||
void add_cover(int level, func_decl* pred, expr* property);
|
||||
|
||||
void updt_params();
|
||||
|
||||
model_ref get_model();
|
||||
|
||||
proof_ref get_proof();
|
||||
|
||||
duality_data *dd(){return _d;}
|
||||
|
||||
private:
|
||||
void display_certificate_non_const(std::ostream& out);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -454,6 +454,44 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief fixedpoint-push command.
|
||||
*/
|
||||
class dl_push_cmd : public cmd {
|
||||
ref<dl_context> m_dl_ctx;
|
||||
public:
|
||||
dl_push_cmd(dl_context * dl_ctx):
|
||||
cmd("fixedpoint-push"),
|
||||
m_dl_ctx(dl_ctx)
|
||||
{}
|
||||
|
||||
virtual char const * get_usage() const { return ""; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "push the fixedpoint context"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
m_dl_ctx->push();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief fixedpoint-pop command.
|
||||
*/
|
||||
class dl_pop_cmd : public cmd {
|
||||
ref<dl_context> m_dl_ctx;
|
||||
public:
|
||||
dl_pop_cmd(dl_context * dl_ctx):
|
||||
cmd("fixedpoint-pop"),
|
||||
m_dl_ctx(dl_ctx)
|
||||
{}
|
||||
|
||||
virtual char const * get_usage() const { return ""; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "pop the fixedpoint context"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
m_dl_ctx->pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_cmds) {
|
||||
dl_context * dl_ctx = alloc(dl_context, ctx, collected_cmds);
|
||||
|
@ -461,6 +499,13 @@ static void install_dl_cmds_aux(cmd_context& ctx, dl_collected_cmds* collected_c
|
|||
ctx.insert(alloc(dl_query_cmd, dl_ctx));
|
||||
ctx.insert(alloc(dl_declare_rel_cmd, dl_ctx));
|
||||
ctx.insert(alloc(dl_declare_var_cmd, dl_ctx));
|
||||
// #ifndef _EXTERNAL_RELEASE
|
||||
// TODO: we need these!
|
||||
#if 1
|
||||
ctx.insert(alloc(dl_push_cmd, dl_ctx)); // not exposed to keep command-extensions simple.
|
||||
ctx.insert(alloc(dl_pop_cmd, dl_ctx));
|
||||
#endif
|
||||
// #endif
|
||||
}
|
||||
|
||||
void install_dl_cmds(cmd_context & ctx) {
|
||||
|
|
|
@ -22,6 +22,7 @@ Revision History:
|
|||
#include "tab_context.h"
|
||||
#include "rel_context.h"
|
||||
#include "pdr_dl_interface.h"
|
||||
#include "duality_dl_interface.h"
|
||||
|
||||
namespace datalog {
|
||||
register_engine::register_engine(): m_ctx(0) {}
|
||||
|
@ -40,6 +41,8 @@ namespace datalog {
|
|||
return alloc(tab, *m_ctx);
|
||||
case CLP_ENGINE:
|
||||
return alloc(clp, *m_ctx);
|
||||
case DUALITY_ENGINE:
|
||||
return alloc(Duality::dl_interface, *m_ctx);
|
||||
case LAST_ENGINE:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
|
|
@ -1125,9 +1125,7 @@ namespace pdr {
|
|||
n->mk_instantiate(r0, r1, binding);
|
||||
proof_ref p1(m), p2(m);
|
||||
p1 = r0->get_proof();
|
||||
if (!p1) {
|
||||
r0->display(dctx, std::cout);
|
||||
}
|
||||
IF_VERBOSE(0, if (!p1) r0->display(dctx, verbose_stream()););
|
||||
SASSERT(p1);
|
||||
pfs[0] = p1;
|
||||
rls[0] = r1;
|
||||
|
|
|
@ -19,6 +19,7 @@ Revision History:
|
|||
|
||||
#include "dl_mk_array_blast.h"
|
||||
#include "qe_util.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -270,7 +271,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
expr_ref fml2(m), body(m), head(m);
|
||||
expr_ref fml1(m), fml2(m), body(m), head(m);
|
||||
body = m.mk_and(new_conjs.size(), new_conjs.c_ptr());
|
||||
head = r.get_head();
|
||||
sub(body);
|
||||
|
@ -287,9 +288,17 @@ namespace datalog {
|
|||
proof_ref p(m);
|
||||
rule_set new_rules(m_ctx);
|
||||
rm.mk_rule(fml2, p, new_rules, r.name());
|
||||
|
||||
|
||||
rule_ref new_rule(rm);
|
||||
if (m_simplifier.transform_rule(new_rules.last(), new_rule)) {
|
||||
if (r.get_proof()) {
|
||||
scoped_proof _sc(m);
|
||||
r.to_formula(fml1);
|
||||
p = m.mk_rewrite(fml1, fml2);
|
||||
p = m.mk_modus_ponens(r.get_proof(), p);
|
||||
new_rule->set_proof(m, p);
|
||||
}
|
||||
rules.add_rule(new_rule.get());
|
||||
rm.mk_rule_rewrite_proof(r, *new_rule.get());
|
||||
TRACE("dl", new_rule->display(m_ctx, tout << "new rule\n"););
|
||||
|
|
|
@ -25,6 +25,7 @@ Revision History:
|
|||
#include "filter_model_converter.h"
|
||||
#include "dl_mk_interp_tail_simplifier.h"
|
||||
#include "fixedpoint_params.hpp"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -268,7 +269,8 @@ namespace datalog {
|
|||
r->to_formula(fml);
|
||||
if (blast(r, fml)) {
|
||||
proof_ref pr(m);
|
||||
if (m_context.generate_proof_trace()) {
|
||||
if (r->get_proof()) {
|
||||
scoped_proof _sc(m);
|
||||
pr = m.mk_asserted(fml); // loses original proof of r.
|
||||
}
|
||||
// TODO add logic for pc:
|
||||
|
|
|
@ -341,7 +341,6 @@ namespace datalog {
|
|||
}
|
||||
head = mk_head(source, *result, r.get_head(), cnt);
|
||||
fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head);
|
||||
rule_ref_vector added_rules(rm);
|
||||
proof_ref pr(m);
|
||||
rm.mk_rule(fml, pr, *result);
|
||||
TRACE("dl", result->last()->display(m_ctx, tout););
|
||||
|
|
|
@ -527,6 +527,9 @@ namespace datalog {
|
|||
|
||||
|
||||
bool mk_rule_inliner::do_eager_inlining(rule * r, rule_set const& rules, rule_ref& res) {
|
||||
if (r->has_negation()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SASSERT(rules.is_closed());
|
||||
const rule_stratifier& strat = rules.get_stratifier();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue