3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00

added facility to persist model transformations

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-11-02 00:05:52 -05:00
commit fd49a0c89c
195 changed files with 3601 additions and 2139 deletions

View file

@ -10,7 +10,6 @@ z3_add_component(muz
dl_rule_transformer.cpp
dl_util.cpp
hnf.cpp
proof_utils.cpp
rule_properties.cpp
COMPONENT_DEPENDENCIES
aig_tactic

View file

@ -53,7 +53,7 @@ Example from Boogie:
#include "muz/base/dl_boogie_proof.h"
#include "model/model_pp.h"
#include "muz/base/proof_utils.h"
#include "ast/proofs/proof_utils.h"
#include "ast/ast_pp.h"
#include "ast/ast_util.h"

View file

@ -453,7 +453,8 @@ namespace datalog {
return new_pred;
}
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
SASSERT(rl);
m_rule_fmls.push_back(rl);
m_rule_names.push_back(name);
m_rule_bounds.push_back(bound);
@ -461,7 +462,7 @@ namespace datalog {
void context::flush_add_rules() {
datalog::rule_manager& rm = get_rule_manager();
scoped_proof_mode _scp(m, generate_proof_trace()?PGM_FINE:PGM_DISABLED);
scoped_proof_mode _scp(m, generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
while (m_rule_fmls_head < m_rule_fmls.size()) {
expr* fml = m_rule_fmls[m_rule_fmls_head].get();
proof* p = generate_proof_trace()?m.mk_asserted(fml):0;

View file

@ -141,7 +141,7 @@ namespace datalog {
void rule_manager::mk_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_FINE:PGM_DISABLED);
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
proof_ref pr(p, m);
expr_ref fml1(m);
bind_variables(fml, true, fml1);
@ -343,7 +343,7 @@ namespace datalog {
}
TRACE("dl", tout << rule_expr << "\n";);
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_FINE:PGM_DISABLED);
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
proof_ref pr(m);
if (m_ctx.generate_proof_trace()) {
pr = m.mk_asserted(rule_expr);

View file

@ -11,7 +11,7 @@ Abstract:
Author:
Leonardo de Moura (leonardo) 2010-05-20.
Krystof Hoder 2010
Revision History:
@ -31,6 +31,7 @@ Revision History:
#include "util/statistics.h"
#include "util/stopwatch.h"
#include "util/lbool.h"
#include "util/container_util.h"
namespace datalog {
@ -381,129 +382,6 @@ namespace datalog {
*/
void apply_subst(expr_ref_vector& tgt, expr_ref_vector const& sub);
// -----------------------------------
//
// container functions
//
// -----------------------------------
template<class Set1, class Set2>
void set_intersection(Set1 & tgt, const Set2 & src) {
svector<typename Set1::data> to_remove;
typename Set1::iterator vit = tgt.begin();
typename Set1::iterator vend = tgt.end();
for(;vit!=vend;++vit) {
typename Set1::data itm=*vit;
if(!src.contains(itm)) {
to_remove.push_back(itm);
}
}
while(!to_remove.empty()) {
tgt.remove(to_remove.back());
to_remove.pop_back();
}
}
template<class Set>
void set_difference(Set & tgt, const Set & to_remove) {
typename Set::iterator vit = to_remove.begin();
typename Set::iterator vend = to_remove.end();
for(;vit!=vend;++vit) {
typename Set::data itm=*vit;
tgt.remove(itm);
}
}
template<class Set1, class Set2>
void set_union(Set1 & tgt, const Set2 & to_add) {
typename Set2::iterator vit = to_add.begin();
typename Set2::iterator vend = to_add.end();
for(;vit!=vend;++vit) {
typename Set1::data itm=*vit;
tgt.insert(itm);
}
}
void idx_set_union(idx_set & tgt, const idx_set & src);
template<class T>
void unite_disjoint_maps(T & tgt, const T & src) {
typename T::iterator it = src.begin();
typename T::iterator end = src.end();
for(; it!=end; ++it) {
SASSERT(!tgt.contains(it->m_key));
tgt.insert(it->m_key, it->m_value);
}
}
template<class T, class U>
void collect_map_range(T & acc, const U & map) {
typename U::iterator it = map.begin();
typename U::iterator end = map.end();
for(; it!=end; ++it) {
acc.push_back(it->m_value);
}
}
template<class T>
void print_container(const T & begin, const T & end, std::ostream & out) {
T it = begin;
out << "(";
bool first = true;
for(; it!=end; ++it) {
if(first) { first = false; } else { out << ","; }
out << (*it);
}
out << ")";
}
template<class T>
void print_container(const T & cont, std::ostream & out) {
print_container(cont.begin(), cont.end(), out);
}
template<class T, class M>
void print_container(const ref_vector<T,M> & cont, std::ostream & out) {
print_container(cont.c_ptr(), cont.c_ptr() + cont.size(), out);
}
template<class T>
void print_map(const T & cont, std::ostream & out) {
typename T::iterator it = cont.begin();
typename T::iterator end = cont.end();
out << "(";
bool first = true;
for(; it!=end; ++it) {
if(first) { first = false; } else { out << ","; }
out << it->m_key << "->" << it->m_value;
}
out << ")";
}
template<class It, class V>
unsigned find_index(const It & begin, const It & end, const V & val) {
unsigned idx = 0;
It it = begin;
for(; it!=end; it++, idx++) {
if(*it==val) {
return idx;
}
}
return UINT_MAX;
}
template<class T, class U>
bool containers_equal(const T & begin1, const T & end1, const U & begin2, const U & end2) {
T it1 = begin1;
U it2 = begin2;
for(; it1!=end1 && it2!=end2; ++it1, ++it2) {
if(*it1!=*it2) {
return false;
}
}
return it1==end1 && it2==end2;
}
template<class T, class U>
bool vectors_equal(const T & c1, const U & c2) {
@ -521,6 +399,8 @@ namespace datalog {
return true;
}
void idx_set_union(idx_set & tgt, const idx_set & src);
template<class T>
struct default_obj_chash {
unsigned operator()(T const& cont, unsigned i) const {

View file

@ -1,680 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
#include "muz/base/dl_util.h"
#include "muz/base/proof_utils.h"
#include "ast/ast_smt2_pp.h"
#include "ast/rewriter/var_subst.h"
class reduce_hypotheses {
typedef obj_hashtable<expr> expr_set;
ast_manager& m;
// reference for any expression created by the tranformation
expr_ref_vector m_refs;
// currently computed result
obj_map<proof,proof*> m_cache;
// map conclusions to closed proofs that derive them
obj_map<expr, proof*> m_units;
// currently active units
ptr_vector<expr> m_units_trail;
// size of m_units_trail at the last push
unsigned_vector m_limits;
// map from proofs to active hypotheses
obj_map<proof, expr_set*> m_hypmap;
// refernce train for hypotheses sets
ptr_vector<expr_set> m_hyprefs;
ptr_vector<expr> m_literals;
void reset() {
m_refs.reset();
m_cache.reset();
m_units.reset();
m_units_trail.reset();
m_limits.reset();
std::for_each(m_hyprefs.begin(), m_hyprefs.end(), delete_proc<expr_set>());
m_hypmap.reset();
m_hyprefs.reset();
m_literals.reset();
}
void push() {
m_limits.push_back(m_units_trail.size());
}
void pop() {
unsigned sz = m_limits.back();
while (m_units_trail.size() > sz) {
m_units.remove(m_units_trail.back());
m_units_trail.pop_back();
}
m_limits.pop_back();
}
void get_literals(expr* clause) {
m_literals.reset();
if (m.is_or(clause)) {
m_literals.append(to_app(clause)->get_num_args(), to_app(clause)->get_args());
}
else {
m_literals.push_back(clause);
}
}
void add_hypotheses(proof* p) {
expr_set* hyps = 0;
bool inherited = false;
if (p->get_decl_kind() == PR_HYPOTHESIS) {
hyps = alloc(expr_set);
hyps->insert(m.get_fact(p));
m_hyprefs.push_back(hyps);
}
else {
for (unsigned i = 0; i < m.get_num_parents(p); ++i) {
expr_set* hyps1 = m_hypmap.find(m.get_parent(p, i));
if (hyps1) {
if (!hyps) {
hyps = hyps1;
inherited = true;
continue;
}
if (inherited) {
hyps = alloc(expr_set,*hyps);
m_hyprefs.push_back(hyps);
inherited = false;
}
datalog::set_union(*hyps, *hyps1);
}
}
}
m_hypmap.insert(p, hyps);
}
expr_ref complement_lit(expr* e) {
expr* e1;
if (m.is_not(e, e1)) {
return expr_ref(e1, m);
}
else {
return expr_ref(m.mk_not(e), m);
}
}
bool in_hypotheses(expr* e, expr_set* hyps) {
if (!hyps) {
return false;
}
expr_ref not_e = complement_lit(e);
return hyps->contains(not_e);
}
bool contains_hypothesis(proof* p) {
ptr_vector<proof> todo;
ast_mark visit;
todo.push_back(p);
while (!todo.empty()) {
p = todo.back();
todo.pop_back();
if (visit.is_marked(p)) {
continue;
}
visit.mark(p, true);
if (PR_HYPOTHESIS == p->get_decl_kind()) {
return true;
}
for (unsigned i = 0; i < m.get_num_parents(p); ++i) {
todo.push_back(m.get_parent(p, i));
}
}
return false;
}
bool is_closed(proof* p) {
expr_set* hyps = m_hypmap.find(p);
return !hyps || hyps->empty();
}
public:
reduce_hypotheses(ast_manager& m): m(m), m_refs(m) {}
void operator()(proof_ref& pr) {
proof_ref tmp(m);
tmp = pr;
elim(pr);
reset();
CTRACE("proof_utils", contains_hypothesis(pr),
tout << "Contains hypothesis:\n";
tout << mk_ismt2_pp(tmp, m) << "\n====>\n";
tout << mk_ismt2_pp(pr, m) << "\n";);
}
void elim(proof_ref& p) {
proof_ref tmp(m);
proof* result = p.get();
if (m_cache.find(p, result)) {
p = result;
return;
}
//SASSERT (p.get () == result);
switch(p->get_decl_kind()) {
case PR_HYPOTHESIS:
// replace result by m_units[m.get_fact (p)] if defined
// AG: This is the main step. Replace a hypothesis by a derivation of its consequence
if (!m_units.find(m.get_fact(p), result)) {
// restore ther result back to p
result = p.get();
}
// compute hypothesis of the result
// not clear what 'result' is at this point.
// probably the proof at the top of the call
// XXX not clear why this is re-computed each time
// XXX moreover, m_units are guaranteed to be closed!
// XXX so no hypotheses are needed for them
add_hypotheses(result);
break;
case PR_LEMMA: {
SASSERT(m.get_num_parents(p) == 1);
tmp = m.get_parent(p, 0);
// eliminate hypothesis recursively in the proof of the lemma
elim(tmp);
expr_set* hyps = m_hypmap.find(tmp);
expr_set* new_hyps = 0;
// XXX if the proof is correct, the hypotheses of the tmp
// XXX should be exactly those of the consequence of the lemma
// XXX but if this code actually eliminates hypotheses, the set might be a subset
if (hyps) {
new_hyps = alloc(expr_set, *hyps);
}
expr* fact = m.get_fact(p);
// when hypothesis is a single literal of the form
// (or A B), and the fact of p is (or A B).
if (hyps && hyps->size() == 1 && in_hypotheses(fact, hyps)) {
m_literals.reset();
m_literals.push_back(fact);
}
else {
get_literals(fact);
}
// go over all the literals in the consequence of the lemma
for (unsigned i = 0; i < m_literals.size(); ++i) {
expr* e = m_literals[i];
// if the literal is not in hypothesis, skip it
if (!in_hypotheses(e, hyps)) {
m_literals[i] = m_literals.back();
m_literals.pop_back();
--i;
}
// if the literal is in hypothesis remove it because
// it is not in hypothesis set of the lemma
// XXX but we assume that lemmas have empty hypothesis set.
// XXX eventually every element of new_hyps must be removed!
else {
SASSERT(new_hyps);
expr_ref not_e = complement_lit(e);
SASSERT(new_hyps->contains(not_e));
new_hyps->remove(not_e);
}
}
// killed all hypotheses, so can stop at the lemma since
// we have a closed pf of false
if (m_literals.empty()) {
result = tmp;
}
else {
// create a new lemma, but might be re-creating existing one
expr_ref clause(m);
if (m_literals.size() == 1) {
clause = m_literals[0];
}
else {
clause = m.mk_or(m_literals.size(), m_literals.c_ptr());
}
tmp = m.mk_lemma(tmp, clause);
m_refs.push_back(tmp);
result = tmp;
}
if (new_hyps && new_hyps->empty()) {
dealloc(new_hyps);
new_hyps = 0;
}
m_hypmap.insert(result, new_hyps);
// might push 0 into m_hyprefs. No reason for that
m_hyprefs.push_back(new_hyps);
TRACE("proof_utils",
tout << "New lemma: " << mk_pp(m.get_fact(p), m)
<< "\n==>\n"
<< mk_pp(m.get_fact(result), m) << "\n";
if (hyps) {
expr_set::iterator it = hyps->begin();
expr_set::iterator end = hyps->end();
for (; it != end; ++it) {
tout << "Hypothesis: " << mk_pp(*it, m) << "\n";
}
});
break;
}
case PR_UNIT_RESOLUTION: {
proof_ref_vector parents(m);
// get the clause being resolved with
parents.push_back(m.get_parent(p, 0));
// save state
push();
bool found_false = false;
// for every derivation of a unit literal
for (unsigned i = 1; i < m.get_num_parents(p); ++i) {
// see if it derives false
tmp = m.get_parent(p, i);
elim(tmp);
if (m.is_false(m.get_fact(tmp))) {
// if derived false, the whole pf is false and we can bail out
result = tmp;
found_false = true;
break;
}
// -- otherwise, the fact has not changed. nothing to simplify
SASSERT(m.get_fact(tmp) == m.get_fact(m.get_parent(p, i)));
parents.push_back(tmp);
// remember that we have this derivation while we have not poped the trail
// but only if the proof is closed (i.e., a real unit)
if (is_closed(tmp) && !m_units.contains(m.get_fact(tmp))) {
m_units.insert(m.get_fact(tmp), tmp);
m_units_trail.push_back(m.get_fact(tmp));
}
}
if (found_false) {
pop();
break;
}
// look at the clause being resolved with
tmp = m.get_parent(p, 0);
// remember its fact
expr* old_clause = m.get_fact(tmp);
// attempt to reduce its fact
elim(tmp);
// update parents
parents[0] = tmp;
// if the new fact is false, bail out
expr* clause = m.get_fact(tmp);
if (m.is_false(clause)) {
m_refs.push_back(tmp);
result = tmp;
pop();
break;
}
//
// case where clause is a literal in the old clause.
// i.e., reduce multi-literal clause to a unit
//
if (is_literal_in_clause(clause, old_clause)) {
// if the resulting literal was resolved, get a pf of false and bail out
bool found = false;
for (unsigned i = 1; !found && i < parents.size(); ++i) {
if (m.is_complement(clause, m.get_fact(parents[i].get()))) {
parents[1] = parents[i].get();
parents.resize(2);
result = m.mk_unit_resolution(parents.size(), parents.c_ptr());
m_refs.push_back(result);
add_hypotheses(result);
found = true;
}
}
// else if the resulting literal is not resolved, it is the new consequence
if (!found) {
result = parents[0].get();
}
pop();
break;
}
//
// case where new clause is a subset of old clause.
// the literals in clause should be a subset of literals in old_clause.
//
get_literals(clause);
for (unsigned i = 1; i < parents.size(); ++i) {
bool found = false;
for (unsigned j = 0; j < m_literals.size(); ++j) {
if (m.is_complement(m_literals[j], m.get_fact(parents[i].get()))) {
found = true;
break;
}
}
if (!found) {
// literal was removed as hypothesis.
parents[i] = parents.back();
parents.pop_back();
--i;
}
}
if (parents.size() == 1) {
result = parents[0].get();
}
else {
result = m.mk_unit_resolution(parents.size(), parents.c_ptr());
m_refs.push_back(result);
add_hypotheses(result);
}
pop();
break;
}
default: {
ptr_buffer<expr> args;
bool change = false;
bool found_false = false;
for (unsigned i = 0; i < m.get_num_parents(p); ++i) {
tmp = m.get_parent(p, i);
elim(tmp);
if (m.is_false(m.get_fact(tmp))) {
result = tmp;
found_false = true;
break;
}
// SASSERT(m.get_fact(tmp) == m.get_fact(m.get_parent(p, i)));
change = change || (tmp != m.get_parent(p, i));
args.push_back(tmp);
}
if (found_false) {
break;
}
if (m.has_fact(p)) {
args.push_back(m.get_fact(p));
}
if (change) {
tmp = m.mk_app(p->get_decl(), args.size(), args.c_ptr());
m_refs.push_back(tmp);
}
else {
tmp = p;
}
result = tmp;
add_hypotheses(result);
break;
}
}
SASSERT(m_hypmap.contains(result));
m_cache.insert(p, result);
p = result;
}
bool is_literal_in_clause(expr* fml, expr* clause) {
if (!m.is_or(clause)) {
return false;
}
app* cl = to_app(clause);
for (unsigned i = 0; i < cl->get_num_args(); ++i) {
if (cl->get_arg(i) == fml) {
return true;
}
}
return false;
}
};
void proof_utils::reduce_hypotheses(proof_ref& pr) {
ast_manager& m = pr.get_manager();
class reduce_hypotheses reduce(m);
reduce(pr);
CTRACE("proof_utils", !is_closed(m, pr), tout << mk_pp(pr, m) << "\n";);
}
class proof_is_closed {
ast_manager& m;
ptr_vector<expr> m_literals;
ast_mark m_visit;
void reset() {
m_literals.reset();
m_visit.reset();
}
bool check(proof* p) {
// really just a partial check because nodes may be visited
// already under a different lemma scope.
if (m_visit.is_marked(p)) {
return true;
}
bool result = false;
m_visit.mark(p, true);
switch(p->get_decl_kind()) {
case PR_LEMMA: {
unsigned sz = m_literals.size();
expr* cls = m.get_fact(p);
m_literals.push_back(cls);
if (m.is_or(cls)) {
m_literals.append(to_app(cls)->get_num_args(), to_app(cls)->get_args());
}
SASSERT(m.get_num_parents(p) == 1);
result = check(m.get_parent(p, 0));
m_literals.resize(sz);
break;
}
case PR_HYPOTHESIS: {
expr* fact = m.get_fact(p);
for (unsigned i = 0; i < m_literals.size(); ++i) {
if (m.is_complement(m_literals[i], fact)) {
result = true;
break;
}
}
break;
}
default:
result = true;
for (unsigned i = 0; i < m.get_num_parents(p); ++i) {
if (!check(m.get_parent(p, i))) {
result = false;
break;
}
}
break;
}
return result;
}
public:
proof_is_closed(ast_manager& m): m(m) {}
bool operator()(proof *p) {
bool ok = check(p);
reset();
return ok;
}
};
bool proof_utils::is_closed(ast_manager& m, proof* p) {
proof_is_closed checker(m);
return checker(p);
}
static void permute_unit_resolution(expr_ref_vector& refs, obj_map<proof,proof*>& cache, proof_ref& pr) {
ast_manager& m = pr.get_manager();
proof* pr2 = 0;
proof_ref_vector parents(m);
proof_ref prNew(pr);
if (cache.find(pr, pr2)) {
pr = pr2;
return;
}
for (unsigned i = 0; i < m.get_num_parents(pr); ++i) {
prNew = m.get_parent(pr, i);
permute_unit_resolution(refs, cache, prNew);
parents.push_back(prNew);
}
prNew = pr;
if (pr->get_decl_kind() == PR_UNIT_RESOLUTION &&
parents[0]->get_decl_kind() == PR_TH_LEMMA) {
/*
Unit resolution:
T1: (or l_1 ... l_n l_1' ... l_m')
T2: (not l_1)
...
T(n+1): (not l_n)
[unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m')
Th lemma:
T1: (not l_1)
...
Tn: (not l_n)
[th-lemma T1 ... Tn]: (or l_{n+1} ... l_m)
Such that (or l_1 .. l_n l_{n+1} .. l_m) is a theory axiom.
Implement conversion:
T1 |- not l_1 ... Tn |- not l_n
------------------------------- TH_LEMMA
(or k_1 .. k_m j_1 ... j_m) S1 |- not k_1 ... Sm |- not k_m
-------------------------------------------------------------- UNIT_RESOLUTION
(or j_1 .. j_m)
|->
T1 |- not l_1 ... Tn |- not l_n S1 |- not k_1 ... Sm |- not k_m
---------------------------------------------------------------- TH_LEMMA
(or j_1 .. j_m)
*/
proof_ref_vector premises(m);
proof* thLemma = parents[0].get();
for (unsigned i = 0; i < m.get_num_parents(thLemma); ++i) {
premises.push_back(m.get_parent(thLemma, i));
}
for (unsigned i = 1; i < parents.size(); ++i) {
premises.push_back(parents[i].get());
}
parameter const* params = thLemma->get_decl()->get_parameters();
unsigned num_params = thLemma->get_decl()->get_num_parameters();
SASSERT(params[0].is_symbol());
family_id tid = m.mk_family_id(params[0].get_symbol());
SASSERT(tid != null_family_id);
// AG: This can break a theory lemma. In particular, for Farkas lemmas the coefficients
// AG: for the literals propagated from the unit resolution are missing.
// AG: Why is this a good thing to do?
// AG: This can lead to merging of the units with other terms in interpolation,
// AG: but without farkas coefficients this does not make sense
prNew = m.mk_th_lemma(tid, m.get_fact(pr),
premises.size(), premises.c_ptr(), num_params-1, params+1);
}
else {
ptr_vector<expr> args;
for (unsigned i = 0; i < parents.size(); ++i) {
args.push_back(parents[i].get());
}
if (m.has_fact(pr)) {
args.push_back(m.get_fact(pr));
}
prNew = m.mk_app(pr->get_decl(), args.size(), args.c_ptr());
}
cache.insert(pr, prNew);
refs.push_back(prNew);
pr = prNew;
}
// permute unit resolution over Theory lemmas to track premises.
void proof_utils::permute_unit_resolution(proof_ref& pr) {
expr_ref_vector refs(pr.get_manager());
obj_map<proof,proof*> cache;
::permute_unit_resolution(refs, cache, pr);
}
class push_instantiations_up_cl {
ast_manager& m;
public:
push_instantiations_up_cl(ast_manager& m): m(m) {}
void operator()(proof_ref& p) {
expr_ref_vector s0(m);
p = push(p, s0);
}
private:
proof* push(proof* p, expr_ref_vector const& sub) {
proof_ref_vector premises(m);
expr_ref conclusion(m);
svector<std::pair<unsigned, unsigned> > positions;
vector<expr_ref_vector> substs;
if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) {
for (unsigned i = 0; i < premises.size(); ++i) {
compose(substs[i], sub);
premises[i] = push(premises[i].get(), substs[i]);
substs[i].reset();
}
instantiate(sub, conclusion);
return
m.mk_hyper_resolve(premises.size(), premises.c_ptr(), conclusion,
positions,
substs);
}
if (sub.empty()) {
return p;
}
if (m.is_modus_ponens(p)) {
SASSERT(m.get_num_parents(p) == 2);
proof* p0 = m.get_parent(p, 0);
proof* p1 = m.get_parent(p, 1);
if (m.get_fact(p0) == m.get_fact(p)) {
return push(p0, sub);
}
expr* e1, *e2;
if (m.is_rewrite(p1, e1, e2) &&
is_quantifier(e1) && is_quantifier(e2) &&
to_quantifier(e1)->get_num_decls() == to_quantifier(e2)->get_num_decls()) {
expr_ref r1(e1,m), r2(e2,m);
instantiate(sub, r1);
instantiate(sub, r2);
p1 = m.mk_rewrite(r1, r2);
return m.mk_modus_ponens(push(p0, sub), p1);
}
}
premises.push_back(p);
substs.push_back(sub);
conclusion = m.get_fact(p);
instantiate(sub, conclusion);
return m.mk_hyper_resolve(premises.size(), premises.c_ptr(), conclusion, positions, substs);
}
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;
}
}
void instantiate(expr_ref_vector const& sub, expr_ref& fml) {
if (sub.empty()) {
return;
}
if (!is_forall(fml)) {
return;
}
quantifier* q = to_quantifier(fml);
if (q->get_num_decls() != sub.size()) {
TRACE("proof_utils", tout << "quantifier has different number of variables than substitution";
tout << mk_pp(q, m) << "\n";
tout << sub.size() << "\n";);
return;
}
var_subst(m, false)(q->get_expr(), sub.size(), sub.c_ptr(), fml);
}
};
void proof_utils::push_instantiations_up(proof_ref& pr) {
push_instantiations_up_cl push(pr.get_manager());
push(pr);
}

View file

@ -1,48 +0,0 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
proof_utils.h
Abstract:
Utilities for transforming proofs.
Author:
Nikolaj Bjorner (nbjorner) 2012-10-12.
Revision History:
--*/
#ifndef PROOF_UTILS_H_
#define PROOF_UTILS_H_
class proof_utils {
public:
/**
\brief reduce the set of hypotheses used in the proof.
*/
static void reduce_hypotheses(proof_ref& pr);
/**
\brief Check that a proof does not contain open hypotheses.
*/
static bool is_closed(ast_manager& m, proof* p);
/**
\brief Permute unit resolution rule with th-lemma
*/
static void permute_unit_resolution(proof_ref& pr);
/**
\brief Push instantiations created in hyper-resolutions up to leaves.
This produces a "ground" proof where leaves are annotated by instantiations.
*/
static void push_instantiations_up(proof_ref& pr);
};
#endif

View file

@ -189,11 +189,12 @@ public:
m_bound = bound;
m_arg_idx++;
}
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); }
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); m_t = nullptr; }
virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; }
virtual void finalize(cmd_context & ctx) {
}
virtual void execute(cmd_context & ctx) {
if (!m_t) throw cmd_exception("invalid rule, expected formula");
m_dl_ctx->add_rule(m_t, m_name, m_bound);
}
};

View file

@ -41,9 +41,8 @@ Notes:
#include "ast/ast_smt2_pp.h"
#include "qe/qe_lite.h"
#include "ast/ast_ll_pp.h"
#include "ast/proof_checker/proof_checker.h"
#include "ast/proofs/proof_checker.h"
#include "smt/smt_value_sort.h"
#include "muz/base/proof_utils.h"
#include "muz/base/dl_boogie_proof.h"
#include "ast/scoped_proof.h"
#include "tactic/core/blast_term_ite_tactic.h"
@ -1825,7 +1824,7 @@ namespace pdr {
m_core_generalizers.push_back(alloc(core_multi_generalizer, *this, 0));
}
if (!classify.is_bool()) {
m.toggle_proof_mode(PGM_FINE);
m.toggle_proof_mode(PGM_ENABLED);
m_fparams.m_arith_bound_prop = BP_NONE;
m_fparams.m_arith_auto_config_simplex = true;
m_fparams.m_arith_propagate_eqs = false;

View file

@ -31,7 +31,7 @@ Revision History:
#include "ast/rewriter/th_rewriter.h"
#include "ast/ast_ll_pp.h"
#include "tactic/arith/arith_bounds_tactic.h"
#include "muz/base/proof_utils.h"
#include "ast/proofs/proof_utils.h"
#include "ast/reg_decl_plugins.h"
@ -372,7 +372,7 @@ namespace pdr {
farkas_learner::farkas_learner(smt_params& params, ast_manager& outer_mgr)
: m_proof_params(get_proof_params(params)),
m_pr(PGM_FINE),
m_pr(PGM_ENABLED),
m_constr(0),
m_combine_farkas_coefficients(true),
p2o(m_pr, outer_mgr),
@ -733,8 +733,8 @@ namespace pdr {
}
else {
expr_set* hyps3 = alloc(expr_set);
datalog::set_union(*hyps3, *hyps);
datalog::set_union(*hyps3, *hyps2);
set_union(*hyps3, *hyps);
set_union(*hyps3, *hyps2);
hyps = hyps3;
hyprefs.push_back(hyps);
}
@ -795,7 +795,7 @@ namespace pdr {
case PR_LEMMA: {
expr_set* hyps2 = alloc(expr_set);
hyprefs.push_back(hyps2);
datalog::set_union(*hyps2, *hyps);
set_union(*hyps2, *hyps);
hyps = hyps2;
expr* fml = m.get_fact(p);
hyps->remove(fml);

View file

@ -81,7 +81,7 @@ namespace pdr {
m_gen(n, core0, uses_level1);
new_cores.push_back(std::make_pair(core0, uses_level1));
obj_hashtable<expr> core_exprs, core1_exprs;
datalog::set_union(core_exprs, core0);
set_union(core_exprs, core0);
for (unsigned i = 0; i < old_core.size(); ++i) {
expr* lit = old_core[i].get();
if (core_exprs.contains(lit)) {
@ -94,8 +94,8 @@ namespace pdr {
if (core1.size() < old_core.size()) {
new_cores.push_back(std::make_pair(core1, uses_level1));
core1_exprs.reset();
datalog::set_union(core1_exprs, core1);
datalog::set_intersection(core_exprs, core1_exprs);
set_union(core1_exprs, core1);
set_intersection(core_exprs, core1_exprs);
}
}
}

View file

@ -128,7 +128,7 @@ namespace datalog {
void set_reg(reg_idx i, reg_type val) {
if (i >= m_registers.size()) {
check_overflow(i);
m_registers.resize(i+1,0);
m_registers.resize(i+1);
}
if (m_registers[i]) {
m_registers[i]->deallocate();

View file

@ -465,7 +465,7 @@ namespace datalog {
unsigned sz = r.get_signature().size();
ptr_vector<expr> subst_arg;
subst_arg.resize(sz, 0);
subst_arg.resize(sz);
unsigned ofs = sz-1;
for (unsigned i=0; i<sz; i++) {
SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));

View file

@ -7,7 +7,6 @@ z3_add_component(spacer
spacer_farkas_learner.cpp
spacer_generalizers.cpp
spacer_manager.cpp
spacer_marshal.cpp
spacer_prop_solver.cpp
spacer_smt_context_manager.cpp
spacer_sym_mux.cpp
@ -15,11 +14,9 @@ z3_add_component(spacer
spacer_itp_solver.cpp
spacer_virtual_solver.cpp
spacer_legacy_mbp.cpp
spacer_proof_utils.cpp
spacer_unsat_core_learner.cpp
spacer_unsat_core_plugin.cpp
spacer_matrix.cpp
spacer_min_cut.cpp
spacer_antiunify.cpp
spacer_mev_array.cpp
spacer_qe_project.cpp

View file

@ -40,7 +40,7 @@ Notes:
#include "ast/ast_smt2_pp.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_util.h"
#include "ast/proof_checker/proof_checker.h"
#include "ast/proofs/proof_checker.h"
#include "smt/smt_value_sort.h"
#include "ast/scoped_proof.h"
#include "muz/spacer/spacer_qe_project.h"
@ -2139,7 +2139,7 @@ void context::reset_lemma_generalizers()
void context::init_lemma_generalizers(datalog::rule_set& rules)
{
reset_lemma_generalizers();
m.toggle_proof_mode(PGM_FINE);
m.toggle_proof_mode(PGM_ENABLED);
smt_params &fparams = m_pm.fparams ();
if (!m_params.spacer_eq_prop ()) {
fparams.m_arith_bound_prop = BP_NONE;

View file

@ -31,7 +31,7 @@ Revision History:
#include "muz/spacer/spacer_farkas_learner.h"
#include "ast/rewriter/th_rewriter.h"
#include "ast/ast_ll_pp.h"
#include "muz/base/proof_utils.h"
#include "ast/proofs/proof_utils.h"
#include "ast/reg_decl_plugins.h"
#include "smt/smt_farkas_util.h"
@ -231,8 +231,8 @@ void farkas_learner::get_lemmas(proof* root, expr_set const& bs, expr_ref_vector
hyps = hyps2;
} else {
expr_set* hyps3 = alloc(expr_set);
datalog::set_union(*hyps3, *hyps);
datalog::set_union(*hyps3, *hyps2);
set_union(*hyps3, *hyps);
set_union(*hyps3, *hyps2);
hyps = hyps3;
hyprefs.push_back(hyps);
}
@ -291,7 +291,7 @@ void farkas_learner::get_lemmas(proof* root, expr_set const& bs, expr_ref_vector
case PR_LEMMA: {
expr_set* hyps2 = alloc(expr_set);
hyprefs.push_back(hyps2);
datalog::set_union(*hyps2, *hyps);
set_union(*hyps2, *hyps);
hyps = hyps2;
expr* fml = m.get_fact(p);
hyps->remove(fml);

View file

@ -138,8 +138,8 @@ public:
{return m_solver.get_num_assumptions();}
virtual expr * get_assumption(unsigned idx) const
{return m_solver.get_assumption(idx);}
virtual std::ostream &display(std::ostream &out) const
{m_solver.display(out); return out;}
virtual std::ostream &display(std::ostream &out, unsigned n, expr* const* es) const
{ return m_solver.display(out, n, es); }
/* check_sat_result interface */
@ -174,7 +174,7 @@ public:
public:
scoped_bg(itp_solver &s) : m_s(s), m_bg_sz(m_s.get_num_bg()) {}
~scoped_bg()
{if(m_s.get_num_bg() > m_bg_sz) { m_s.pop_bg(m_s.get_num_bg() - m_bg_sz); }}
{if (m_s.get_num_bg() > m_bg_sz) { m_s.pop_bg(m_s.get_num_bg() - m_bg_sz); }}
};
};
}

View file

@ -23,9 +23,9 @@
#include "ast/ast_smt2_pp.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_util.h"
#include "ast/proof_checker/proof_checker.h"
#include "ast/proofs/proof_checker.h"
#include "smt/smt_value_sort.h"
#include "muz/base/proof_utils.h"
#include "ast/proofs/proof_utils.h"
#include "ast/scoped_proof.h"
#include "muz/spacer/spacer_qe_project.h"
#include "tactic/core/blast_term_ite_tactic.h"

View file

@ -1,56 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_marshal.cpp
Abstract:
marshaling and unmarshaling of expressions
--*/
#include "muz/spacer/spacer_marshal.h"
#include <sstream>
#include "cmd_context/cmd_context.h"
#include "parsers/smt2/smt2parser.h"
#include "util/vector.h"
#include "ast/ast_smt_pp.h"
#include "ast/ast_pp.h"
namespace spacer {
std::ostream &marshal(std::ostream &os, expr_ref e, ast_manager &m)
{
ast_smt_pp pp(m);
pp.display_smt2(os, e);
return os;
}
std::string marshal(expr_ref e, ast_manager &m)
{
std::stringstream ss;
marshal(ss, e, m);
return ss.str();
}
expr_ref unmarshal(std::istream &is, ast_manager &m)
{
cmd_context ctx(false, &m);
ctx.set_ignore_check(true);
if (!parse_smt2_commands(ctx, is)) { return expr_ref(0, m); }
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
if (it == end) { return expr_ref(m.mk_true(), m); }
unsigned size = static_cast<unsigned>(end - it);
return expr_ref(m.mk_and(size, it), m);
}
expr_ref unmarshal(std::string s, ast_manager &m)
{
std::istringstream is(s);
return unmarshal(is, m);
}
}

View file

@ -1,30 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_marshal.h
Abstract:
marshaling and unmarshaling of expressions
--*/
#ifndef _SPACER_MARSHAL_H_
#define _SPACER_MARSHAL_H_
#include <string>
#include <iostream>
#include "ast/ast.h"
namespace spacer {
std::ostream &marshal(std::ostream &os, expr_ref e, ast_manager &m);
std::string marshal(expr_ref e, ast_manager &m);
expr_ref unmarshal(std::string s, ast_manager &m);
expr_ref unmarshal(std::istream &is, ast_manager &m);
}
#endif

View file

@ -1,289 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_min_cut.cpp
Abstract:
min cut solver
Author:
Bernhard Gleiss
Revision History:
--*/
#include "muz/spacer/spacer_min_cut.h"
namespace spacer {
spacer_min_cut::spacer_min_cut()
{
m_n = 2;
// push back two empty vectors for source and sink
m_edges.push_back(vector<std::pair<unsigned, unsigned>>());
m_edges.push_back(vector<std::pair<unsigned, unsigned>>());
}
unsigned spacer_min_cut::new_node()
{
return m_n++;
}
void spacer_min_cut::add_edge(unsigned int i, unsigned int j, unsigned int capacity)
{
if (i >= m_edges.size())
{
m_edges.resize(i + 1);
}
m_edges[i].insert(std::make_pair(j, 1));
STRACE("spacer.mincut",
verbose_stream() << "adding edge (" << i << "," << j << ")\n";
);
}
void spacer_min_cut::compute_min_cut(vector<unsigned>& cut_nodes)
{
if (m_n == 2)
{
return;
}
m_d.resize(m_n);
m_pred.resize(m_n);
// compute initial distances and number of nodes
compute_initial_distances();
unsigned i = 0;
while (m_d[0] < m_n)
{
unsigned j = get_admissible_edge(i);
if (j < m_n)
{
// advance(i)
m_pred[j] = i;
i = j;
// if i is the sink, augment path
if (i == 1)
{
augment_path();
i = 0;
}
}
else
{
// retreat
compute_distance(i);
if (i != 0)
{
i = m_pred[i];
}
}
}
// split nodes into reachable and unreachable ones
vector<bool> reachable(m_n);
compute_reachable_nodes(reachable);
// find all edges between reachable and unreachable nodes and for each such edge, add corresponding lemma to unsat-core
compute_cut_and_add_lemmas(reachable, cut_nodes);
}
void spacer_min_cut::compute_initial_distances()
{
vector<unsigned> todo;
vector<bool> visited(m_n);
todo.push_back(0); // start at the source, since we do postorder traversel
while (!todo.empty())
{
unsigned current = todo.back();
// if we haven't already visited current
if (!visited[current]) {
bool existsUnvisitedParent = false;
// add unprocessed parents to stack for DFS. If there is at least one unprocessed parent, don't compute the result
// for current now, but wait until those unprocessed parents are processed.
for (unsigned i = 0, sz = m_edges[current].size(); i < sz; ++i)
{
unsigned parent = m_edges[current][i].first;
// if we haven't visited the current parent yet
if(!visited[parent])
{
// add it to the stack
todo.push_back(parent);
existsUnvisitedParent = true;
}
}
// if we already visited all parents, we can visit current too
if (!existsUnvisitedParent) {
visited[current] = true;
todo.pop_back();
compute_distance(current); // I.H. all parent distances are already computed
}
}
else {
todo.pop_back();
}
}
}
unsigned spacer_min_cut::get_admissible_edge(unsigned i)
{
for (const auto& pair : m_edges[i])
{
if (pair.second > 0 && m_d[i] == m_d[pair.first] + 1)
{
return pair.first;
}
}
return m_n; // no element found
}
void spacer_min_cut::augment_path()
{
// find bottleneck capacity
unsigned max = std::numeric_limits<unsigned int>::max();
unsigned k = 1;
while (k != 0)
{
unsigned l = m_pred[k];
for (const auto& pair : m_edges[l])
{
if (pair.first == k)
{
if (max > pair.second)
{
max = pair.second;
}
}
}
k = l;
}
k = 1;
while (k != 0)
{
unsigned l = m_pred[k];
// decrease capacity
for (auto& pair : m_edges[l])
{
if (pair.first == k)
{
pair.second -= max;
}
}
// increase reverse flow
bool already_exists = false;
for (auto& pair : m_edges[k])
{
if (pair.first == l)
{
already_exists = true;
pair.second += max;
}
}
if (!already_exists)
{
m_edges[k].insert(std::make_pair(l, max));
}
k = l;
}
}
void spacer_min_cut::compute_distance(unsigned i)
{
if (i == 1) // sink node
{
m_d[1] = 0;
}
else
{
unsigned min = std::numeric_limits<unsigned int>::max();
// find edge (i,j) with positive residual capacity and smallest distance
for (const auto& pair : m_edges[i])
{
if (pair.second > 0)
{
unsigned tmp = m_d[pair.first] + 1;
if (tmp < min)
{
min = tmp;
}
}
}
m_d[i] = min;
}
}
void spacer_min_cut::compute_reachable_nodes(vector<bool>& reachable)
{
vector<unsigned> todo;
todo.push_back(0);
while (!todo.empty())
{
unsigned current = todo.back();
todo.pop_back();
if (!reachable[current])
{
reachable[current] = true;
for (const auto& pair : m_edges[current])
{
if (pair.second > 0)
{
todo.push_back(pair.first);
}
}
}
}
}
void spacer_min_cut::compute_cut_and_add_lemmas(vector<bool>& reachable, vector<unsigned>& cut_nodes)
{
vector<unsigned> todo;
vector<bool> visited(m_n);
todo.push_back(0);
while (!todo.empty())
{
unsigned current = todo.back();
todo.pop_back();
if (!visited[current])
{
visited[current] = true;
for (const auto& pair : m_edges[current])
{
unsigned successor = pair.first;
if (reachable[successor])
{
todo.push_back(successor);
}
else
{
cut_nodes.push_back(successor);
}
}
}
}
}
}

View file

@ -1,53 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_min_cut.h
Abstract:
min cut solver
Author:
Bernhard Gleiss
Revision History:
--*/
#ifndef _SPACER_MIN_CUT_H_
#define _SPACER_MIN_CUT_H_
#include "ast/ast.h"
#include "util/vector.h"
namespace spacer {
class spacer_min_cut {
public:
spacer_min_cut();
unsigned new_node();
void add_edge(unsigned i, unsigned j, unsigned capacity);
void compute_min_cut(vector<unsigned>& cut_nodes);
private:
unsigned m_n; // number of vertices in the graph
vector<vector<std::pair<unsigned, unsigned> > > m_edges; // map from node to all outgoing edges together with their weights (also contains "reverse edges")
vector<unsigned> m_d; // approximation of distance from node to sink in residual graph
vector<unsigned> m_pred; // predecessor-information for reconstruction of augmenting path
vector<expr*> m_node_to_formula; // maps each node to the corresponding formula in the original proof
void compute_initial_distances();
unsigned get_admissible_edge(unsigned i);
void augment_path();
void compute_distance(unsigned i);
void compute_reachable_nodes(vector<bool>& reachable);
void compute_cut_and_add_lemmas(vector<bool>& reachable, vector<unsigned>& cut_nodes);
};
}
#endif

View file

@ -1,332 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_proof_utils.cpp
Abstract:
Utilities to traverse and manipulate proofs
Author:
Bernhard Gleiss
Arie Gurfinkel
Revision History:
--*/
#include "muz/spacer/spacer_proof_utils.h"
#include "ast/ast_util.h"
#include "ast/ast_pp.h"
#include "ast/proof_checker/proof_checker.h"
namespace spacer {
ProofIteratorPostOrder::ProofIteratorPostOrder(proof* root, ast_manager& manager) : m(manager)
{m_todo.push_back(root);}
bool ProofIteratorPostOrder::hasNext()
{return !m_todo.empty();}
/*
* iterative post-order depth-first search (DFS) through the proof DAG
*/
proof* ProofIteratorPostOrder::next()
{
while (!m_todo.empty()) {
proof* currentNode = m_todo.back();
// if we haven't already visited the current unit
if (!m_visited.is_marked(currentNode)) {
bool existsUnvisitedParent = false;
// add unprocessed premises to stack for DFS. If there is at least one unprocessed premise, don't compute the result
// for currentProof now, but wait until those unprocessed premises are processed.
for (unsigned i = 0; i < m.get_num_parents(currentNode); ++i) {
SASSERT(m.is_proof(currentNode->get_arg(i)));
proof* premise = to_app(currentNode->get_arg(i));
// if we haven't visited the current premise yet
if (!m_visited.is_marked(premise)) {
// add it to the stack
m_todo.push_back(premise);
existsUnvisitedParent = true;
}
}
// if we already visited all parent-inferences, we can visit the inference too
if (!existsUnvisitedParent) {
m_visited.mark(currentNode, true);
m_todo.pop_back();
return currentNode;
}
} else {
m_todo.pop_back();
}
}
// we have already iterated through all inferences
return NULL;
}
class reduce_hypotheses {
ast_manager &m;
// tracking all created expressions
expr_ref_vector m_pinned;
// cache for the transformation
obj_map<proof, proof*> m_cache;
// map from unit literals to their hypotheses-free derivations
obj_map<expr, proof*> m_units;
// -- all hypotheses in the the proof
obj_hashtable<expr> m_hyps;
// marks hypothetical proofs
ast_mark m_hypmark;
// stack
ptr_vector<proof> m_todo;
void reset()
{
m_cache.reset();
m_units.reset();
m_hyps.reset();
m_hypmark.reset();
m_pinned.reset();
}
bool compute_mark1(proof *pr)
{
bool hyp_mark = false;
// lemmas clear all hypotheses
if (!m.is_lemma(pr)) {
for (unsigned i = 0, sz = m.get_num_parents(pr); i < sz; ++i) {
if (m_hypmark.is_marked(m.get_parent(pr, i))) {
hyp_mark = true;
break;
}
}
}
m_hypmark.mark(pr, hyp_mark);
return hyp_mark;
}
void compute_marks(proof* pr)
{
proof *p;
ProofIteratorPostOrder pit(pr, m);
while (pit.hasNext()) {
p = pit.next();
if (m.is_hypothesis(p)) {
m_hypmark.mark(p, true);
m_hyps.insert(m.get_fact(p));
} else {
bool hyp_mark = compute_mark1(p);
// collect units that are hyp-free and are used as hypotheses somewhere
if (!hyp_mark && m.has_fact(p) && m_hyps.contains(m.get_fact(p)))
{ m_units.insert(m.get_fact(p), p); }
}
}
}
void find_units(proof *pr)
{
// optional. not implemented yet.
}
void reduce(proof* pf, proof_ref &out)
{
proof *res = NULL;
m_todo.reset();
m_todo.push_back(pf);
ptr_buffer<proof> args;
bool dirty = false;
while (!m_todo.empty()) {
proof *p, *tmp, *pp;
unsigned todo_sz;
p = m_todo.back();
if (m_cache.find(p, tmp)) {
res = tmp;
m_todo.pop_back();
continue;
}
dirty = false;
args.reset();
todo_sz = m_todo.size();
for (unsigned i = 0, sz = m.get_num_parents(p); i < sz; ++i) {
pp = m.get_parent(p, i);
if (m_cache.find(pp, tmp)) {
args.push_back(tmp);
dirty = dirty || pp != tmp;
} else {
m_todo.push_back(pp);
}
}
if (todo_sz < m_todo.size()) { continue; }
else { m_todo.pop_back(); }
if (m.is_hypothesis(p)) {
// hyp: replace by a corresponding unit
if (m_units.find(m.get_fact(p), tmp)) {
res = tmp;
} else { res = p; }
}
else if (!dirty) { res = p; }
else if (m.is_lemma(p)) {
//lemma: reduce the premise; remove reduced consequences from conclusion
SASSERT(args.size() == 1);
res = mk_lemma_core(args.get(0), m.get_fact(p));
compute_mark1(res);
} else if (m.is_unit_resolution(p)) {
// unit: reduce untis; reduce the first premise; rebuild unit resolution
res = mk_unit_resolution_core(args.size(), args.c_ptr());
compute_mark1(res);
} else {
// other: reduce all premises; reapply
if (m.has_fact(p)) { args.push_back(to_app(m.get_fact(p))); }
SASSERT(p->get_decl()->get_arity() == args.size());
res = m.mk_app(p->get_decl(), args.size(), (expr * const*)args.c_ptr());
m_pinned.push_back(res);
compute_mark1(res);
}
SASSERT(res);
m_cache.insert(p, res);
if (m.has_fact(res) && m.is_false(m.get_fact(res))) { break; }
}
out = res;
}
// returns true if (hypothesis (not a)) would be reduced
bool is_reduced(expr *a)
{
expr_ref e(m);
if (m.is_not(a)) { e = to_app(a)->get_arg(0); }
else { e = m.mk_not(a); }
return m_units.contains(e);
}
proof *mk_lemma_core(proof *pf, expr *fact)
{
ptr_buffer<expr> args;
expr_ref lemma(m);
if (m.is_or(fact)) {
for (unsigned i = 0, sz = to_app(fact)->get_num_args(); i < sz; ++i) {
expr *a = to_app(fact)->get_arg(i);
if (!is_reduced(a))
{ args.push_back(a); }
}
} else if (!is_reduced(fact))
{ args.push_back(fact); }
if (args.size() == 0) { return pf; }
else if (args.size() == 1) {
lemma = args.get(0);
} else {
lemma = m.mk_or(args.size(), args.c_ptr());
}
proof* res = m.mk_lemma(pf, lemma);
m_pinned.push_back(res);
if (m_hyps.contains(lemma))
{ m_units.insert(lemma, res); }
return res;
}
proof *mk_unit_resolution_core(unsigned num_args, proof* const *args)
{
ptr_buffer<proof> pf_args;
pf_args.push_back(args [0]);
app *cls_fact = to_app(m.get_fact(args[0]));
ptr_buffer<expr> cls;
if (m.is_or(cls_fact)) {
for (unsigned i = 0, sz = cls_fact->get_num_args(); i < sz; ++i)
{ cls.push_back(cls_fact->get_arg(i)); }
} else { cls.push_back(cls_fact); }
// construct new resovent
ptr_buffer<expr> new_fact_cls;
bool found;
// XXX quadratic
for (unsigned i = 0, sz = cls.size(); i < sz; ++i) {
found = false;
for (unsigned j = 1; j < num_args; ++j) {
if (m.is_complement(cls.get(i), m.get_fact(args [j]))) {
found = true;
pf_args.push_back(args [j]);
break;
}
}
if (!found) {
new_fact_cls.push_back(cls.get(i));
}
}
SASSERT(new_fact_cls.size() + pf_args.size() - 1 == cls.size());
expr_ref new_fact(m);
new_fact = mk_or(m, new_fact_cls.size(), new_fact_cls.c_ptr());
// create new proof step
proof *res = m.mk_unit_resolution(pf_args.size(), pf_args.c_ptr(), new_fact);
m_pinned.push_back(res);
return res;
}
// reduce all units, if any unit reduces to false return true and put its proof into out
bool reduce_units(proof_ref &out)
{
proof_ref res(m);
for (auto entry : m_units) {
reduce(entry.get_value(), res);
if (m.is_false(m.get_fact(res))) {
out = res;
return true;
}
res.reset();
}
return false;
}
public:
reduce_hypotheses(ast_manager &m) : m(m), m_pinned(m) {}
void operator()(proof_ref &pr)
{
compute_marks(pr);
if (!reduce_units(pr)) {
reduce(pr.get(), pr);
}
reset();
}
};
void reduce_hypotheses(proof_ref &pr)
{
ast_manager &m = pr.get_manager();
class reduce_hypotheses hypred(m);
hypred(pr);
DEBUG_CODE(proof_checker pc(m);
expr_ref_vector side(m);
SASSERT(pc.check(pr, side));
);
}
}

View file

@ -1,43 +0,0 @@
/*++
Copyright (c) 2017 Arie Gurfinkel
Module Name:
spacer_proof_utils.cpp
Abstract:
Utilities to traverse and manipulate proofs
Author:
Bernhard Gleiss
Arie Gurfinkel
Revision History:
--*/
#ifndef _SPACER_PROOF_UTILS_H_
#define _SPACER_PROOF_UTILS_H_
#include "ast/ast.h"
namespace spacer {
/*
* iterator, which traverses the proof in depth-first post-order.
*/
class ProofIteratorPostOrder {
public:
ProofIteratorPostOrder(proof* refutation, ast_manager& manager);
bool hasNext();
proof* next();
private:
ptr_vector<proof> m_todo;
ast_mark m_visited; // the proof nodes we have already visited
ast_manager& m;
};
void reduce_hypotheses(proof_ref &pr);
}
#endif

View file

@ -66,7 +66,6 @@ class peq {
app_ref m_peq; // partial equality application
app_ref m_eq; // equivalent std equality using def. of partial eq
array_util m_arr_u;
ast_eq_proc m_eq_proc; // for checking if two asts are equal
public:
static const char* PARTIAL_EQ;
@ -102,7 +101,7 @@ peq::peq (app* p, ast_manager& m):
VERIFY (is_partial_eq (p));
SASSERT (m_arr_u.is_array (m_lhs) &&
m_arr_u.is_array (m_rhs) &&
m_eq_proc (m.get_sort (m_lhs), m.get_sort (m_rhs)));
ast_eq_proc() (m.get_sort (m_lhs), m.get_sort (m_rhs)));
for (unsigned i = 2; i < p->get_num_args (); i++) {
m_diff_indices.push_back (p->get_arg (i));
}
@ -121,7 +120,7 @@ peq::peq (expr* lhs, expr* rhs, unsigned num_indices, expr * const * diff_indice
{
SASSERT (m_arr_u.is_array (lhs) &&
m_arr_u.is_array (rhs) &&
m_eq_proc (m.get_sort (lhs), m.get_sort (rhs)));
ast_eq_proc() (m.get_sort (lhs), m.get_sort (rhs)));
ptr_vector<sort> sorts;
sorts.push_back (m.get_sort (m_lhs));
sorts.push_back (m.get_sort (m_rhs));

View file

@ -41,7 +41,7 @@ void unsat_core_learner::compute_unsat_core(proof *root, expr_set& asserted_b, e
// transform proof in order to get a proof which is better suited for unsat-core-extraction
proof_ref pr(root, m);
spacer::reduce_hypotheses(pr);
reduce_hypotheses(pr);
STRACE("spacer.unsat_core_learner",
verbose_stream() << "Reduced proof:\n" << mk_ismt2_pp(pr, m) << "\n";
);
@ -50,7 +50,7 @@ void unsat_core_learner::compute_unsat_core(proof *root, expr_set& asserted_b, e
collect_symbols_b(asserted_b);
// traverse proof
ProofIteratorPostOrder it(root, m);
proof_post_order it(root, m);
while (it.hasNext())
{
proof* currentNode = it.next();
@ -138,7 +138,7 @@ void unsat_core_learner::compute_unsat_core(proof *root, expr_set& asserted_b, e
std::unordered_map<unsigned, unsigned> id_to_small_id;
unsigned counter = 0;
ProofIteratorPostOrder it2(root, m);
proof_post_order it2(root, m);
while (it2.hasNext())
{
proof* currentNode = it2.next();

View file

@ -20,7 +20,7 @@ Revision History:
#include "ast/ast.h"
#include "muz/spacer/spacer_util.h"
#include "muz/spacer/spacer_proof_utils.h"
#include "ast/proofs/proof_utils.h"
namespace spacer {

View file

@ -20,13 +20,13 @@ Revision History:
#include "ast/rewriter/bool_rewriter.h"
#include "ast/arith_decl_plugin.h"
#include "ast/proofs/proof_utils.h"
#include "solver/solver.h"
#include "smt/smt_farkas_util.h"
#include "smt/smt_solver.h"
#include "muz/spacer/spacer_proof_utils.h"
#include "muz/spacer/spacer_matrix.h"
#include "muz/spacer/spacer_unsat_core_plugin.h"
#include "muz/spacer/spacer_unsat_core_learner.h"
@ -735,7 +735,7 @@ void unsat_core_plugin_farkas_lemma::compute_linear_combination(const vector<rat
m_node_to_formula[node_other] = m.get_fact(i);
m_node_to_formula[node_i] = m.get_fact(i);
m_min_cut.add_edge(node_other, node_i, 1);
m_min_cut.add_edge(node_other, node_i);
}
}
@ -765,12 +765,12 @@ void unsat_core_plugin_farkas_lemma::compute_linear_combination(const vector<rat
m_node_to_formula[node_j] = m.get_fact(j);
m_node_to_formula[node_other] = m.get_fact(j);
m_min_cut.add_edge(node_j, node_other, 1);
m_min_cut.add_edge(node_j, node_other);
}
}
// finally connect nodes
m_min_cut.add_edge(node_i, node_j, 1);
m_min_cut.add_edge(node_i, node_j);
}
/*
@ -779,7 +779,7 @@ void unsat_core_plugin_farkas_lemma::compute_linear_combination(const vector<rat
*/
void unsat_core_plugin_min_cut::finalize()
{
vector<unsigned int> cut_nodes;
unsigned_vector cut_nodes;
m_min_cut.compute_min_cut(cut_nodes);
for (unsigned cut_node : cut_nodes)

View file

@ -19,7 +19,7 @@ Revision History:
#define _SPACER_UNSAT_CORE_PLUGIN_H_
#include "ast/ast.h"
#include "muz/spacer/spacer_min_cut.h"
#include "util/min_cut.h"
namespace spacer {
@ -109,7 +109,7 @@ private:
vector<expr*> m_node_to_formula; // maps each node to the corresponding formula in the original proof
spacer_min_cut m_min_cut;
min_cut m_min_cut;
};
}
#endif

View file

@ -72,73 +72,67 @@ namespace spacer {
//
model_evaluator_util::model_evaluator_util(ast_manager& m) :
m(m), m_mev(NULL)
{ reset (NULL); }
m(m), m_mev(nullptr) {
reset (nullptr);
}
model_evaluator_util::~model_evaluator_util() {reset (NULL);}
void model_evaluator_util::reset(model* model)
{
void model_evaluator_util::reset(model* model) {
if (m_mev) {
dealloc(m_mev);
m_mev = NULL;
}
m_model = model;
if (!m_model) { return; }
if (!m_model) { return; }
m_mev = alloc(model_evaluator, *m_model);
}
bool model_evaluator_util::eval(expr *e, expr_ref &result, bool model_completion)
{
bool model_evaluator_util::eval(expr *e, expr_ref &result, bool model_completion) {
m_mev->set_model_completion (model_completion);
try {
m_mev->operator() (e, result);
return true;
} catch (model_evaluator_exception &ex) {
}
catch (model_evaluator_exception &ex) {
(void)ex;
TRACE("spacer_model_evaluator", tout << ex.msg () << "\n";);
return false;
}
}
bool model_evaluator_util::eval(const expr_ref_vector &v,
expr_ref& res, bool model_completion)
{
expr_ref& res, bool model_completion) {
expr_ref e(m);
e = mk_and (v);
return eval(e, res, model_completion);
}
bool model_evaluator_util::is_true(const expr_ref_vector &v)
{
bool model_evaluator_util::is_true(const expr_ref_vector &v) {
expr_ref res(m);
return eval (v, res, false) && m.is_true (res);
}
bool model_evaluator_util::is_false(expr *x)
{
bool model_evaluator_util::is_false(expr *x) {
expr_ref res(m);
return eval(x, res, false) && m.is_false (res);
}
bool model_evaluator_util::is_true(expr *x)
{
bool model_evaluator_util::is_true(expr *x) {
expr_ref res(m);
return eval(x, res, false) && m.is_true (res);
}
void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
{
void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml) {
ast_manager& m = fml.get_manager();
expr_ref_vector conjs(m);
flatten_and(fml, conjs);
obj_map<expr, unsigned> diseqs;
expr* n, *lhs, *rhs;
for (unsigned i = 0; i < conjs.size(); ++i) {
if (m.is_not(conjs[i].get(), n) &&
m.is_eq(n, lhs, rhs)) {
if (m.is_not(conjs[i].get(), n) && m.is_eq(n, lhs, rhs)) {
if (!m.is_value(rhs)) {
std::swap(lhs, rhs);
}
@ -155,14 +149,12 @@ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
expr_ref val(m), tmp(m);
proof_ref pr(m);
pr = m.mk_asserted(m.mk_true());
obj_map<expr, unsigned>::iterator it = diseqs.begin();
obj_map<expr, unsigned>::iterator end = diseqs.end();
for (; it != end; ++it) {
if (it->m_value >= threshold) {
model.eval(it->m_key, val);
sub.insert(it->m_key, val, pr);
conjs.push_back(m.mk_eq(it->m_key, val));
num_deleted += it->m_value;
for (auto const& kv : diseqs) {
if (kv.m_value >= threshold) {
model.eval(kv.m_key, val);
sub.insert(kv.m_key, val, pr);
conjs.push_back(m.mk_eq(kv.m_key, val));
num_deleted += kv.m_value;
}
}
if (orig_size < conjs.size()) {
@ -178,14 +170,17 @@ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
SASSERT(orig_size <= 1 + conjs.size());
if (i + 1 == orig_size) {
// no-op.
} else if (orig_size <= conjs.size()) {
}
else if (orig_size <= conjs.size()) {
// no-op
} else {
}
else {
SASSERT(orig_size == 1 + conjs.size());
--orig_size;
--i;
}
} else {
}
else {
conjs[i] = tmp;
}
}
@ -202,9 +197,8 @@ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
ast_manager& m;
public:
ite_hoister(ast_manager& m): m(m) {}
br_status mk_app_core(func_decl* f, unsigned num_args, expr* const* args, expr_ref& result)
{
br_status mk_app_core(func_decl* f, unsigned num_args, expr* const* args, expr_ref& result) {
if (m.is_ite(f)) {
return BR_FAILED;
}
@ -233,13 +227,12 @@ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
struct ite_hoister_cfg: public default_rewriter_cfg {
ite_hoister m_r;
bool rewrite_patterns() const { return false; }
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr)
{
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
return m_r.mk_app_core(f, num, args, result);
}
ite_hoister_cfg(ast_manager & m, params_ref const & p):m_r(m) {}
};
class ite_hoister_star : public rewriter_tpl<ite_hoister_cfg> {
ite_hoister_cfg m_cfg;
public:
@ -247,9 +240,8 @@ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml)
rewriter_tpl<ite_hoister_cfg>(m, false, m_cfg),
m_cfg(m, p) {}
};
void hoist_non_bool_if(expr_ref& fml)
{
void hoist_non_bool_if(expr_ref& fml) {
ast_manager& m = fml.get_manager();
scoped_no_proof _sp(m);
params_ref p;
@ -266,8 +258,7 @@ void hoist_non_bool_if(expr_ref& fml)
bool m_is_dl;
bool m_test_for_utvpi;
bool is_numeric(expr* e) const
{
bool is_numeric(expr* e) const {
if (a.is_numeral(e)) {
return true;
}
@ -278,13 +269,11 @@ void hoist_non_bool_if(expr_ref& fml)
return false;
}
bool is_arith_expr(expr *e) const
{
bool is_arith_expr(expr *e) const {
return is_app(e) && a.get_family_id() == to_app(e)->get_family_id();
}
bool is_offset(expr* e) const
{
bool is_offset(expr* e) const {
if (a.is_numeral(e)) {
return true;
}
@ -315,47 +304,44 @@ void hoist_non_bool_if(expr_ref& fml)
return !is_arith_expr(e);
}
bool is_minus_one(expr const * e) const
{
rational r;
return a.is_numeral(e, r) && r.is_minus_one();
bool is_minus_one(expr const * e) const {
rational r;
return a.is_numeral(e, r) && r.is_minus_one();
}
bool test_ineq(expr* e) const
{
bool test_ineq(expr* e) const {
SASSERT(a.is_le(e) || a.is_ge(e) || m.is_eq(e));
SASSERT(to_app(e)->get_num_args() == 2);
expr * lhs = to_app(e)->get_arg(0);
expr * rhs = to_app(e)->get_arg(1);
if (is_offset(lhs) && is_offset(rhs))
{ return true; }
{ return true; }
if (!is_numeric(rhs))
{ std::swap(lhs, rhs); }
{ std::swap(lhs, rhs); }
if (!is_numeric(rhs))
{ return false; }
{ return false; }
// lhs can be 'x' or '(+ x (* -1 y))'
if (is_offset(lhs))
{ return true; }
{ return true; }
expr* arg1, *arg2;
if (!a.is_add(lhs, arg1, arg2))
{ return false; }
{ return false; }
// x
if (m_test_for_utvpi) {
return is_offset(arg1) && is_offset(arg2);
}
if (is_arith_expr(arg1))
{ std::swap(arg1, arg2); }
{ std::swap(arg1, arg2); }
if (is_arith_expr(arg1))
{ return false; }
{ return false; }
// arg2: (* -1 y)
expr* m1, *m2;
if (!a.is_mul(arg2, m1, m2))
{ return false; }
{ return false; }
return is_minus_one(m1) && is_offset(m2);
}
bool test_eq(expr* e) const
{
bool test_eq(expr* e) const {
expr* lhs, *rhs;
VERIFY(m.is_eq(e, lhs, rhs));
if (!a.is_int_real(lhs)) {
@ -370,9 +356,8 @@ void hoist_non_bool_if(expr_ref& fml)
!a.is_mul(lhs) &&
!a.is_mul(rhs);
}
bool test_term(expr* e) const
{
bool test_term(expr* e) const {
if (m.is_bool(e)) {
return true;
}
@ -490,7 +475,7 @@ bool is_utvpi_logic(ast_manager& m, unsigned num_fmls, expr* const* fmls)
* eliminate simple equalities using qe_lite
* then, MBP for Booleans (substitute), reals (based on LW), ints (based on Cooper), and arrays
*/
void qe_project (ast_manager& m, app_ref_vector& vars, expr_ref& fml,
void qe_project (ast_manager& m, app_ref_vector& vars, expr_ref& fml,
const model_ref& M, bool reduce_all_selects, bool use_native_mbp,
bool dont_sub)
{

View file

@ -74,15 +74,6 @@ inline std::ostream& operator<<(std::ostream& out, pp_level const& p)
}
struct scoped_watch {
stopwatch &m_sw;
scoped_watch (stopwatch &sw, bool reset=false): m_sw(sw)
{
if(reset) { m_sw.reset(); }
m_sw.start ();
}
~scoped_watch () {m_sw.stop ();}
};
typedef ptr_vector<app> app_vector;

View file

@ -23,7 +23,8 @@ Notes:
#include "muz/spacer/spacer_util.h"
#include "ast/rewriter/bool_rewriter.h"
#include "ast/proof_checker/proof_checker.h"
#include "ast/proofs/proof_checker.h"
#include "ast/proofs/proof_utils.h"
#include "ast/scoped_proof.h"
@ -64,172 +65,11 @@ virtual_solver::~virtual_solver()
}
namespace {
static bool matches_fact(expr_ref_vector &args, expr* &match)
{
ast_manager &m = args.get_manager();
expr *fact = args.back();
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i) {
expr *arg = args.get(i);
if (m.is_proof(arg) &&
m.has_fact(to_app(arg)) &&
m.get_fact(to_app(arg)) == fact) {
match = arg;
return true;
}
}
return false;
}
class elim_aux_assertions {
app_ref m_aux;
public:
elim_aux_assertions(app_ref aux) : m_aux(aux) {}
// TBD: move to ast/proofs/elim_aux_assertions
void mk_or_core(expr_ref_vector &args, expr_ref &res)
{
ast_manager &m = args.get_manager();
unsigned j = 0;
for (unsigned i = 0, sz = args.size(); i < sz; ++i) {
if (m.is_false(args.get(i))) { continue; }
if (i != j) { args [j] = args.get(i); }
++j;
}
SASSERT(j >= 1);
res = j > 1 ? m.mk_or(j, args.c_ptr()) : args.get(0);
}
void mk_app(func_decl *decl, expr_ref_vector &args, expr_ref &res)
{
ast_manager &m = args.get_manager();
bool_rewriter brwr(m);
if (m.is_or(decl))
{ mk_or_core(args, res); }
else if (m.is_iff(decl) && args.size() == 2)
// avoiding simplifying equalities. In particular,
// we don't want (= (not a) (not b)) to be reduced to (= a b)
{ res = m.mk_iff(args.get(0), args.get(1)); }
else
{ brwr.mk_app(decl, args.size(), args.c_ptr(), res); }
}
void operator()(ast_manager &m, proof *pr, proof_ref &res)
{
DEBUG_CODE(proof_checker pc(m);
expr_ref_vector side(m);
SASSERT(pc.check(pr, side));
);
obj_map<app, app*> cache;
bool_rewriter brwr(m);
// for reference counting of new proofs
app_ref_vector pinned(m);
ptr_vector<app> todo;
todo.push_back(pr);
expr_ref not_aux(m);
not_aux = m.mk_not(m_aux);
expr_ref_vector args(m);
while (!todo.empty()) {
app *p, *r;
expr *a;
p = todo.back();
if (cache.find(pr, r)) {
todo.pop_back();
continue;
}
SASSERT(!todo.empty() || pr == p);
bool dirty = false;
unsigned todo_sz = todo.size();
args.reset();
for (unsigned i = 0, sz = p->get_num_args(); i < sz; ++i) {
expr* arg = p->get_arg(i);
if (arg == m_aux.get()) {
dirty = true;
args.push_back(m.mk_true());
} else if (arg == not_aux.get()) {
dirty = true;
args.push_back(m.mk_false());
}
// skip (asserted m_aux)
else if (m.is_asserted(arg, a) && a == m_aux.get()) {
dirty = true;
}
// skip (hypothesis m_aux)
else if (m.is_hypothesis(arg, a) && a == m_aux.get()) {
dirty = true;
} else if (is_app(arg) && cache.find(to_app(arg), r)) {
dirty |= (arg != r);
args.push_back(r);
} else if (is_app(arg))
{ todo.push_back(to_app(arg)); }
else
// -- not an app
{ args.push_back(arg); }
}
if (todo_sz < todo.size()) {
// -- process parents
args.reset();
continue;
}
// ready to re-create
app_ref newp(m);
if (!dirty) { newp = p; }
else if (m.is_unit_resolution(p)) {
if (args.size() == 2)
// unit resolution with m_aux that got collapsed to nothing
{ newp = to_app(args.get(0)); }
else {
ptr_vector<proof> parents;
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i)
{ parents.push_back(to_app(args.get(i))); }
SASSERT(parents.size() == args.size() - 1);
newp = m.mk_unit_resolution(parents.size(), parents.c_ptr());
// XXX the old and new facts should be
// equivalent. The test here is much
// stronger. It might need to be relaxed.
SASSERT(m.get_fact(newp) == args.back());
pinned.push_back(newp);
}
} else if (matches_fact(args, a)) {
newp = to_app(a);
} else {
expr_ref papp(m);
mk_app(p->get_decl(), args, papp);
newp = to_app(papp.get());
pinned.push_back(newp);
}
cache.insert(p, newp);
todo.pop_back();
CTRACE("virtual",
p->get_decl_kind() == PR_TH_LEMMA &&
p->get_decl()->get_parameter(0).get_symbol() == "arith" &&
p->get_decl()->get_num_parameters() > 1 &&
p->get_decl()->get_parameter(1).get_symbol() == "farkas",
tout << "Old pf: " << mk_pp(p, m) << "\n"
<< "New pf: " << mk_pp(newp, m) << "\n";);
}
proof *r;
VERIFY(cache.find(pr, r));
DEBUG_CODE(
proof_checker pc(m);
expr_ref_vector side(m);
SASSERT(pc.check(r, side));
);
res = r ;
}
};
}
proof *virtual_solver::get_proof()
@ -349,15 +189,16 @@ void virtual_solver::push_core()
m_context.push();
}
}
void virtual_solver::pop_core(unsigned n)
{
void virtual_solver::pop_core(unsigned n) {
SASSERT(!m_pushed || get_scope_level() > 0);
if (m_pushed) {
SASSERT(!m_in_delay_scope);
m_context.pop(n);
m_pushed = get_scope_level() - n > 0;
} else
{ m_in_delay_scope = get_scope_level() - n > 0; }
}
else {
m_in_delay_scope = get_scope_level() - n > 0;
}
}
void virtual_solver::get_unsat_core(ptr_vector<expr> &r)

View file

@ -94,8 +94,6 @@ public:
virtual void reset();
virtual void set_progress_callback(progress_callback *callback) {UNREACHABLE();}
virtual void assert_lemma(expr* e) { NOT_IMPLEMENTED_YET(); }
virtual expr_ref lookahead(const expr_ref_vector &,const expr_ref_vector &) { return expr_ref(m.mk_true(), m); }
virtual expr_ref cube() { return expr_ref(m.mk_true(), m); }
virtual solver *translate(ast_manager &m, params_ref const &p);
@ -136,6 +134,9 @@ private:
void refresh();
smt_params &fparams() { return m_fparams; }
public:
virtual_solver_factory(ast_manager &mgr, smt_params &fparams);
virtual ~virtual_solver_factory();
@ -146,7 +147,6 @@ public:
void collect_param_descrs(param_descrs &r) { /* empty */ }
void set_produce_models(bool f) { m_fparams.m_model = f; }
bool get_produce_models() { return m_fparams.m_model; }
smt_params &fparams() { return m_fparams; }
};
}