mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
re-organizing muz
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
add96bc98f
commit
9e61820125
20 changed files with 73 additions and 42 deletions
|
@ -1,160 +0,0 @@
|
|||
|
||||
|
||||
#include"arith_bounds_tactic.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
|
||||
struct arith_bounds_tactic : public tactic {
|
||||
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
volatile bool m_cancel;
|
||||
|
||||
arith_bounds_tactic(ast_manager& m):
|
||||
m(m),
|
||||
a(m),
|
||||
m_cancel(false)
|
||||
{
|
||||
}
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
m_cancel = false;
|
||||
}
|
||||
|
||||
virtual void operator()(/* in */ goal_ref const & in,
|
||||
/* out */ goal_ref_buffer & result,
|
||||
/* out */ model_converter_ref & mc,
|
||||
/* out */ proof_converter_ref & pc,
|
||||
/* out */ expr_dependency_ref & core) {
|
||||
bounds_arith_subsumption(in, result);
|
||||
}
|
||||
|
||||
virtual tactic* translate(ast_manager& m) {
|
||||
return alloc(arith_bounds_tactic, m);
|
||||
}
|
||||
|
||||
void checkpoint() {
|
||||
if (m_cancel) {
|
||||
throw tactic_exception(TACTIC_CANCELED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct info { rational r; unsigned idx; bool is_strict;};
|
||||
|
||||
/**
|
||||
\brief Basic arithmetic subsumption simplification based on bounds.
|
||||
*/
|
||||
|
||||
void mk_proof(proof_ref& pr, goal_ref const& s, unsigned i, unsigned j) {
|
||||
if (s->proofs_enabled()) {
|
||||
proof* th_lemma = m.mk_th_lemma(a.get_family_id(), m.mk_implies(s->form(i), s->form(j)), 0, 0);
|
||||
pr = m.mk_modus_ponens(s->pr(i), th_lemma);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool is_le_or_lt(expr* e, expr*& e1, expr*& e2, bool& is_strict) {
|
||||
bool is_negated = m.is_not(e, e);
|
||||
if ((!is_negated && (a.is_le(e, e1, e2) || a.is_ge(e, e2, e1))) ||
|
||||
(is_negated && (a.is_lt(e, e2, e1) || a.is_gt(e, e1, e2)))) {
|
||||
is_strict = false;
|
||||
return true;
|
||||
}
|
||||
if ((!is_negated && (a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1))) ||
|
||||
(is_negated && (a.is_le(e, e2, e1) || a.is_ge(e, e1, e2)))) {
|
||||
is_strict = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bounds_arith_subsumption(goal_ref const& g, goal_ref_buffer& result) {
|
||||
info inf;
|
||||
rational r;
|
||||
goal_ref s(g); // initialize result.
|
||||
obj_map<expr, info> lower, upper;
|
||||
expr* e1, *e2;
|
||||
TRACE("arith_subsumption", s->display(tout); );
|
||||
for (unsigned i = 0; i < s->size(); ++i) {
|
||||
checkpoint();
|
||||
expr* lemma = s->form(i);
|
||||
bool is_strict = false;
|
||||
bool is_lower = false;
|
||||
if (!is_le_or_lt(lemma, e1, e2, is_strict)) {
|
||||
continue;
|
||||
}
|
||||
// e1 <= e2 or e1 < e2
|
||||
if (a.is_numeral(e2, r)) {
|
||||
is_lower = true;
|
||||
}
|
||||
else if (a.is_numeral(e1, r)) {
|
||||
is_lower = false;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
proof_ref new_pr(m);
|
||||
|
||||
if (is_lower && upper.find(e1, inf)) {
|
||||
if (inf.r > r || (inf.r == r && is_strict && !inf.is_strict)) {
|
||||
mk_proof(new_pr, s, i, inf.idx);
|
||||
s->update(inf.idx, m.mk_true(), new_pr);
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
upper.insert(e1, inf);
|
||||
}
|
||||
else {
|
||||
mk_proof(new_pr, s, inf.idx, i);
|
||||
s->update(i, m.mk_true(), new_pr);
|
||||
}
|
||||
}
|
||||
else if (is_lower) {
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
upper.insert(e1, inf);
|
||||
}
|
||||
else if (!is_lower && lower.find(e2, inf)) {
|
||||
if (inf.r < r || (inf.r == r && is_strict && !inf.is_strict)) {
|
||||
mk_proof(new_pr, s, i, inf.idx);
|
||||
s->update(inf.idx, m.mk_true(), new_pr);
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
lower.insert(e2, inf);
|
||||
}
|
||||
else {
|
||||
mk_proof(new_pr, s, inf.idx, i);
|
||||
s->update(i, m.mk_true());
|
||||
}
|
||||
}
|
||||
else if (!is_lower) {
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
lower.insert(e2, inf);
|
||||
}
|
||||
}
|
||||
s->elim_true();
|
||||
result.push_back(s.get());
|
||||
TRACE("arith_subsumption", s->display(tout); );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p) {
|
||||
return alloc(arith_bounds_tactic, m);
|
||||
}
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_bounds_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Fast/rudimentary arithmetic subsumption tactic.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-6
|
||||
|
||||
Notes:
|
||||
|
||||
Background: The Farkas learner in PDR generates tons
|
||||
of inequalities that contain redundancies.
|
||||
It therefore needs a fast way to reduce these redundancies before
|
||||
passing the results to routines that are more expensive.
|
||||
The arith subsumption_strategy encapsulates a rudimentary
|
||||
routine for simplifying inequalities. Additional simplification
|
||||
routines can be added here or composed with this strategy.
|
||||
|
||||
Note: The bound_manager subsumes some of the collection methods used
|
||||
for assembling bounds, but it does not have a way to check for
|
||||
subsumption of atoms.
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_BOUNDS_TACTIC_H_
|
||||
#define _ARITH_BOUNDS_TACTIC_H_
|
||||
#include "tactic.h"
|
||||
|
||||
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
|
@ -31,6 +31,7 @@ Revision History:
|
|||
#include "rewriter_def.h"
|
||||
#include "dl_transforms.h"
|
||||
#include "dl_mk_rule_inliner.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ Revision History:
|
|||
|
||||
#include<sstream>
|
||||
#include<limits>
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"dl_context.h"
|
||||
|
@ -28,6 +26,7 @@ Revision History:
|
|||
#include"ast_smt_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"scoped_proof.h"
|
||||
|
||||
|
||||
namespace datalog {
|
||||
|
|
|
@ -42,6 +42,7 @@ Revision History:
|
|||
#include"bool_rewriter.h"
|
||||
#include"expr_safe_replace.h"
|
||||
#include"filter_model_converter.h"
|
||||
#include"scoped_proof.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
|
|
@ -25,9 +25,10 @@ Revision History:
|
|||
#endif
|
||||
#include"ast_pp.h"
|
||||
#include"bool_rewriter.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"scoped_proof.h"
|
||||
#include"dl_context.h"
|
||||
#include"dl_rule.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"dl_util.h"
|
||||
|
||||
namespace datalog {
|
||||
|
|
|
@ -124,36 +124,6 @@ namespace datalog {
|
|||
*/
|
||||
void display_fact(context & ctx, app * f, std::ostream & out);
|
||||
|
||||
class scoped_proof_mode {
|
||||
ast_manager& m;
|
||||
proof_gen_mode m_mode;
|
||||
public:
|
||||
scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
|
||||
m_mode = m.proof_mode();
|
||||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
|
||||
};
|
||||
|
||||
class scoped_restore_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class variable_intersection
|
||||
|
|
|
@ -19,11 +19,11 @@ Revision History:
|
|||
|
||||
#include "equiv_proof_converter.h"
|
||||
#include "ast_pp.h"
|
||||
#include "dl_util.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
void equiv_proof_converter::insert(expr* fml1, expr* fml2) {
|
||||
if (fml1 != fml2) {
|
||||
datalog::scoped_proof _sp(m);
|
||||
scoped_proof _sp(m);
|
||||
proof_ref p1(m), p2(m), p3(m);
|
||||
p1 = m.mk_asserted(fml1);
|
||||
p2 = m.mk_rewrite(fml1, fml2);
|
||||
|
|
|
@ -46,6 +46,7 @@ Notes:
|
|||
#include "proof_utils.h"
|
||||
#include "dl_boogie_proof.h"
|
||||
#include "qe_util.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
namespace pdr {
|
||||
|
||||
|
@ -1719,7 +1720,7 @@ namespace pdr {
|
|||
}
|
||||
|
||||
proof_ref context::get_proof() const {
|
||||
datalog::scoped_proof _sc(m);
|
||||
scoped_proof _sc(m);
|
||||
proof_ref proof(m);
|
||||
SASSERT(m_last_result == l_true);
|
||||
proof = m_search.get_proof_trace(*this);
|
||||
|
@ -1959,7 +1960,7 @@ namespace pdr {
|
|||
void context::create_children(model_node& n) {
|
||||
SASSERT(n.level() > 0);
|
||||
bool use_model_generalizer = m_params.use_model_generalizer();
|
||||
datalog::scoped_no_proof _sc(m);
|
||||
scoped_no_proof _sc(m);
|
||||
|
||||
pred_transformer& pt = n.pt();
|
||||
model_ref M = n.get_model_ptr();
|
||||
|
|
|
@ -31,8 +31,9 @@ Revision History:
|
|||
#include "dl_mk_slice.h"
|
||||
#include "dl_mk_unfold.h"
|
||||
#include "dl_mk_coalesce.h"
|
||||
#include "model_smt2_pp.h"
|
||||
#include "dl_transforms.h"
|
||||
#include "scoped_proof.h"
|
||||
#include "model_smt2_pp.h"
|
||||
|
||||
using namespace pdr;
|
||||
|
||||
|
@ -149,7 +150,7 @@ lbool dl_interface::query(expr * query) {
|
|||
m_ctx.reopen();
|
||||
m_ctx.replace_rules(old_rules);
|
||||
|
||||
datalog::scoped_restore_proof _sc(m); // update_rules may overwrite the proof mode.
|
||||
scoped_restore_proof _sc(m); // update_rules may overwrite the proof mode.
|
||||
|
||||
m_context->set_proof_converter(m_ctx.get_proof_converter());
|
||||
m_context->set_model_converter(m_ctx.get_model_converter());
|
||||
|
|
|
@ -45,6 +45,7 @@ Notes:
|
|||
#include "poly_rewriter.h"
|
||||
#include "poly_rewriter_def.h"
|
||||
#include "arith_rewriter.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1072,7 +1073,7 @@ namespace pdr {
|
|||
|
||||
void hoist_non_bool_if(expr_ref& fml) {
|
||||
ast_manager& m = fml.get_manager();
|
||||
datalog::scoped_no_proof _sp(m);
|
||||
scoped_no_proof _sp(m);
|
||||
params_ref p;
|
||||
ite_hoister_star ite_rw(m, p);
|
||||
expr_ref tmp(m);
|
||||
|
@ -1419,7 +1420,7 @@ namespace pdr {
|
|||
|
||||
void normalize_arithmetic(expr_ref& t) {
|
||||
ast_manager& m = t.get_manager();
|
||||
datalog::scoped_no_proof _sp(m);
|
||||
scoped_no_proof _sp(m);
|
||||
params_ref p;
|
||||
arith_normalizer_star rw(m, p);
|
||||
expr_ref tmp(m);
|
||||
|
|
55
src/muz/scoped_proof.h
Normal file
55
src/muz/scoped_proof.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
scoped_proof.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Scoped proof environments. Toggles enabling proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-08-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SCOPED_PROOF__H_
|
||||
#define _SCOPED_PROOF_H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
class scoped_proof_mode {
|
||||
ast_manager& m;
|
||||
proof_gen_mode m_mode;
|
||||
public:
|
||||
scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
|
||||
m_mode = m.proof_mode();
|
||||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
|
||||
};
|
||||
|
||||
class scoped_restore_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@ Revision History:
|
|||
#include "datatype_decl_plugin.h"
|
||||
#include "for_each_expr.h"
|
||||
#include "matcher.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
namespace tb {
|
||||
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
unit_subsumption_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Simplify goal using subsumption based on unit propagation.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-6
|
||||
|
||||
--*/
|
||||
|
||||
#include "unit_subsumption_tactic.h"
|
||||
#include "smt_context.h"
|
||||
|
||||
struct unit_subsumption_tactic : public tactic {
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
smt_params m_fparams;
|
||||
volatile bool m_cancel;
|
||||
smt::context m_context;
|
||||
expr_ref_vector m_clauses;
|
||||
unsigned m_clause_count;
|
||||
bit_vector m_is_deleted;
|
||||
unsigned_vector m_deleted;
|
||||
|
||||
unit_subsumption_tactic(
|
||||
ast_manager& m,
|
||||
params_ref const& p):
|
||||
m(m),
|
||||
m_params(p),
|
||||
m_cancel(false),
|
||||
m_context(m, m_fparams, p),
|
||||
m_clauses(m) {
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
m_context.set_cancel_flag(f);
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
set_cancel(false);
|
||||
}
|
||||
|
||||
virtual void operator()(/* in */ goal_ref const & in,
|
||||
/* out */ goal_ref_buffer & result,
|
||||
/* out */ model_converter_ref & mc,
|
||||
/* out */ proof_converter_ref & pc,
|
||||
/* out */ expr_dependency_ref & core) {
|
||||
reduce_core(in, result);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const& p) {
|
||||
m_params = p;
|
||||
// m_context.updt_params(p); does not exist.
|
||||
}
|
||||
|
||||
virtual tactic* translate(ast_manager& m) {
|
||||
return alloc(unit_subsumption_tactic, m, m_params);
|
||||
}
|
||||
|
||||
void checkpoint() {
|
||||
if (m_cancel) {
|
||||
throw tactic_exception(TACTIC_CANCELED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
void reduce_core(goal_ref const& g, goal_ref_buffer& result) {
|
||||
init(g);
|
||||
m_context.push();
|
||||
assert_clauses(g);
|
||||
m_context.push(); // internalize assertions.
|
||||
prune_clauses();
|
||||
goal_ref r(g);
|
||||
insert_result(r);
|
||||
r->elim_true();
|
||||
result.push_back(r.get());
|
||||
m_context.pop(2);
|
||||
TRACE("unit_subsumption_tactic", g->display(tout); r->display(tout););
|
||||
}
|
||||
|
||||
void assert_clauses(goal_ref const& g) {
|
||||
for (unsigned i = 0; i < g->size(); ++i) {
|
||||
m_context.assert_expr(m.mk_iff(new_clause(), g->form(i)));
|
||||
}
|
||||
}
|
||||
|
||||
void prune_clauses() {
|
||||
for (unsigned i = 0; i < m_clause_count; ++i) {
|
||||
prune_clause(i);
|
||||
}
|
||||
}
|
||||
|
||||
void prune_clause(unsigned i) {
|
||||
m_context.push();
|
||||
for (unsigned j = 0; j < m_clause_count; ++j) {
|
||||
if (i == j) {
|
||||
m_context.assert_expr(m.mk_not(m_clauses[j].get()));
|
||||
}
|
||||
else if (!m_is_deleted.get(j)) {
|
||||
m_context.assert_expr(m_clauses[j].get());
|
||||
}
|
||||
}
|
||||
m_context.push(); // force propagation
|
||||
bool is_unsat = m_context.inconsistent();
|
||||
m_context.pop(2);
|
||||
if (is_unsat) {
|
||||
TRACE("unit_subsumption_tactic", tout << "Removing clause " << i << "\n";);
|
||||
m_is_deleted.set(i, true);
|
||||
m_deleted.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void insert_result(goal_ref& result) {
|
||||
for (unsigned i = 0; i < m_deleted.size(); ++i) {
|
||||
result->update(m_deleted[i], m.mk_true()); // TBD proof?
|
||||
}
|
||||
}
|
||||
|
||||
void init(goal_ref const& g) {
|
||||
m_clause_count = 0;
|
||||
m_is_deleted.reset();
|
||||
m_is_deleted.resize(g->size());
|
||||
m_deleted.reset();
|
||||
}
|
||||
|
||||
expr* new_bool(unsigned& count, expr_ref_vector& v, char const* name) {
|
||||
SASSERT(count <= v.size());
|
||||
if (count == v.size()) {
|
||||
v.push_back(m.mk_fresh_const(name, m.mk_bool_sort()));
|
||||
}
|
||||
return v[count++].get();
|
||||
}
|
||||
|
||||
expr* new_clause() {
|
||||
return new_bool(m_clause_count, m_clauses, "#clause");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
tactic * mk_unit_subsumption_tactic(ast_manager & m, params_ref const & p) {
|
||||
return alloc(unit_subsumption_tactic, m, p);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
unit_subsumption_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Simplify goal using subsumption based on unit propagation.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-6
|
||||
|
||||
Notes:
|
||||
|
||||
Background: PDR generates several clauses that subsume each-other.
|
||||
Simplify a goal assuming it is a conjunction of clauses.
|
||||
Subsumed clauses are simplified by using unit-propagation
|
||||
It uses the smt_context for the solver.
|
||||
|
||||
--*/
|
||||
#ifndef _UNIT_SUBSUMPTION_TACTIC_H_
|
||||
#define _UNIT_SUBSUMPTION_TACTIC_H_
|
||||
#include "tactic.h"
|
||||
|
||||
tactic * mk_unit_subsumption_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
/*
|
||||
ADD_TACTIC("unit-subsume-simplify", "unit subsumption simplification.", "mk_unit_subsumption_tactic(m, p)")
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,169 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
vsubst_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Check satisfiability of QF_NRA problems using virtual subsititution quantifier-elimination.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj (nbjorner) 2011-05-16
|
||||
|
||||
Notes:
|
||||
Ported to tactic framework on 2012-02-28
|
||||
It was qfnra_vsubst.cpp
|
||||
|
||||
This goal transformation checks satsifiability
|
||||
of quantifier-free non-linear constraints using
|
||||
virtual substitutions (applies to second-degree polynomials).
|
||||
. identify non-linear variables
|
||||
. use the identified variables as non-linear variables.
|
||||
. give up if there are non-linear variables under uninterpreted scope.
|
||||
give up if there are no non-linear variables.
|
||||
. call quantifier elimination with
|
||||
- non-linear elimination option.
|
||||
- get-first-branch option.
|
||||
. if the first branch is linear, then done.
|
||||
if the result is unsat, then done.
|
||||
if the first branch is non-linear then,
|
||||
check candidate model,
|
||||
perhaps iterate using rewriting or just give up.
|
||||
|
||||
. helpful facilities:
|
||||
. linearize_rewriter
|
||||
a*a*b + a*b = 0 <=> (b+1) = 0 \/ a = 0 \/ b = 0
|
||||
. sign analysis:
|
||||
a*a + b*b + c < 0 => c < 0
|
||||
|
||||
--*/
|
||||
#include"tactic.h"
|
||||
#include"qe.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"extension_model_converter.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
class vsubst_tactic : public tactic {
|
||||
params_ref m_params;
|
||||
|
||||
class get_var_proc {
|
||||
arith_util m_arith;
|
||||
ptr_vector<app>& m_vars;
|
||||
public:
|
||||
get_var_proc(ast_manager & m, ptr_vector<app>& vars) : m_arith(m), m_vars(vars) {}
|
||||
|
||||
void operator()(expr* e) {
|
||||
if (is_app(e)) {
|
||||
app* a = to_app(e);
|
||||
if (m_arith.is_real(e) &&
|
||||
a->get_num_args() == 0 &&
|
||||
a->get_family_id() == null_family_id) {
|
||||
m_vars.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void get_vars(ast_manager & m, expr* fml, ptr_vector<app>& vars) {
|
||||
get_var_proc proc(m, vars);
|
||||
for_each_expr(proc, fml);
|
||||
}
|
||||
|
||||
void main(goal & s, model_converter_ref & mc, params_ref const & p) {
|
||||
ast_manager & m = s.m();
|
||||
|
||||
ptr_vector<expr> fs;
|
||||
for (unsigned i = 0; i < s.size(); ++i) {
|
||||
fs.push_back(s.form(i));
|
||||
}
|
||||
app_ref f(m.mk_and(fs.size(), fs.c_ptr()), m);
|
||||
TRACE("vsubst",
|
||||
s.display(tout);
|
||||
tout << "goal: " << mk_ismt2_pp(f.get(), m) << "\n";);
|
||||
ptr_vector<app> vars;
|
||||
get_vars(m, f.get(), vars);
|
||||
|
||||
if (vars.empty()) {
|
||||
TRACE("vsubst", tout << "no real variables\n";);
|
||||
throw tactic_exception("there are no real variables");
|
||||
}
|
||||
|
||||
smt_params params;
|
||||
params.updt_params(p);
|
||||
params.m_model = false;
|
||||
flet<bool> fl1(params.m_nlquant_elim, true);
|
||||
flet<bool> fl2(params.m_nl_arith_gb, false);
|
||||
TRACE("quant_elim", tout << "Produce models: " << params.m_model << "\n";);
|
||||
|
||||
qe::expr_quant_elim_star1 qelim(m, params);
|
||||
expr_ref g(f, m);
|
||||
qe::def_vector defs(m);
|
||||
lbool is_sat = qelim.first_elim(vars.size(), vars.c_ptr(), g, defs);
|
||||
if (is_sat == l_undef) {
|
||||
TRACE("vsubst", tout << mk_ismt2_pp(g, m) << "\n";);
|
||||
throw tactic_exception("elimination was not successful");
|
||||
}
|
||||
if (!defs.empty()) {
|
||||
extension_model_converter * ev = alloc(extension_model_converter, m);
|
||||
mc = ev;
|
||||
for (unsigned i = defs.size(); i > 0; ) {
|
||||
--i;
|
||||
ev->insert(defs.var(i), defs.def(i));
|
||||
}
|
||||
}
|
||||
|
||||
s.reset();
|
||||
// TBD: wasteful as we already know it is sat or unsat.
|
||||
// TBD: extract model from virtual substitution.
|
||||
s.assert_expr(g);
|
||||
|
||||
TRACE("qfnra_vsubst",
|
||||
tout << "v-subst result:\n";
|
||||
s.display(tout););
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
vsubst_tactic(params_ref const & p):m_params(p) {}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
return alloc(vsubst_tactic, m_params);
|
||||
}
|
||||
|
||||
virtual ~vsubst_tactic() {}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Check satisfiability of an assertion set of QF_NRA
|
||||
by using virtual substitutions.
|
||||
*/
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
SASSERT(g->is_well_sorted());
|
||||
fail_if_proof_generation("vsubst", g);
|
||||
fail_if_unsat_core_generation("vsubst", g);
|
||||
fail_if_model_generation("vsubst", g); // disable for now due to problems with infinitesimals.
|
||||
mc = 0; pc = 0; core = 0; result.reset();
|
||||
|
||||
main(*(g.get()), mc, m_params);
|
||||
|
||||
result.push_back(g.get());
|
||||
SASSERT(g->is_well_sorted());
|
||||
}
|
||||
|
||||
virtual void cleanup(void) {}
|
||||
};
|
||||
|
||||
tactic * mk_vsubst_tactic(ast_manager & m, params_ref const & p) {
|
||||
return alloc(vsubst_tactic, p);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
vsubst_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Check satisfiability of QF_NRA problems using virtual subsititution quantifier-elimination.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj (nbjorner) 2011-05-16
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
--*/
|
||||
#ifndef _VSUBST_TACTIC_H_
|
||||
#define _VSUBST_TACTIC_H_
|
||||
|
||||
#include"params.h"
|
||||
class ast_manager;
|
||||
class tactic;
|
||||
|
||||
tactic * mk_vsubst_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
/*
|
||||
ADD_TACTIC("vsubst", "checks satsifiability of quantifier-free non-linear constraints using virtual substitution.", "mk_vsubst_tactic(m, p)")
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue