3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-23 14:23:40 +00:00

Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable

This commit is contained in:
Christoph M. Wintersteiger 2014-08-22 12:57:45 +01:00
commit f023b8992f
7 changed files with 127 additions and 18 deletions

View file

@ -1152,6 +1152,13 @@ protected:
virtual void LearnFrom(Solver *old_solver) = 0; virtual void LearnFrom(Solver *old_solver) = 0;
/** Return true if the solution be incorrect due to recursion bounding.
That is, the returned "solution" might contain all derivable facts up to the
given recursion bound, but not be actually a fixed point.
*/
virtual bool IsResultRecursionBounded() = 0;
virtual ~Solver(){} virtual ~Solver(){}
static Solver *Create(const std::string &solver_class, RPFP *rpfp); static Solver *Create(const std::string &solver_class, RPFP *rpfp);

View file

@ -768,6 +768,29 @@ namespace Duality {
annot.Simplify(); annot.Simplify();
} }
bool recursionBounded;
/** See if the solution might be bounded. */
void TestRecursionBounded(){
recursionBounded = false;
if(RecursionBound == -1)
return;
for(unsigned i = 0; i < nodes.size(); i++){
Node *node = nodes[i];
std::vector<Node *> &insts = insts_of_node[node];
for(unsigned j = 0; j < insts.size(); j++)
if(indset->Contains(insts[j]))
if(NodePastRecursionBound(insts[j])){
recursionBounded = true;
return;
}
}
}
bool IsResultRecursionBounded(){
return recursionBounded;
}
/** Generate a proposed solution of the input RPFP from /** Generate a proposed solution of the input RPFP from
the unwinding, by unioning the instances of each node. */ the unwinding, by unioning the instances of each node. */
void GenSolutionFromIndSet(bool with_markers = false){ void GenSolutionFromIndSet(bool with_markers = false){
@ -1026,6 +1049,7 @@ namespace Duality {
timer_stop("ProduceCandidatesForExtension"); timer_stop("ProduceCandidatesForExtension");
if(candidates.empty()){ if(candidates.empty()){
GenSolutionFromIndSet(); GenSolutionFromIndSet();
TestRecursionBounded();
return true; return true;
} }
Candidate cand = candidates.front(); Candidate cand = candidates.front();

View file

@ -53,6 +53,7 @@ namespace datalog {
MEMOUT, MEMOUT,
INPUT_ERROR, INPUT_ERROR,
APPROX, APPROX,
BOUNDED,
CANCELED CANCELED
}; };
@ -304,6 +305,8 @@ namespace datalog {
\brief Retrieve predicates \brief Retrieve predicates
*/ */
func_decl_set const& get_predicates() const { return m_preds; } func_decl_set const& get_predicates() const { return m_preds; }
ast_ref_vector const &get_pinned() const {return m_pinned; }
bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); } bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); }
bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); } bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); }

View file

@ -36,6 +36,7 @@ Revision History:
#include "model_v2_pp.h" #include "model_v2_pp.h"
#include "fixedpoint_params.hpp" #include "fixedpoint_params.hpp"
#include "used_vars.h" #include "used_vars.h"
#include "func_decl_dependencies.h"
// template class symbol_table<family_id>; // template class symbol_table<family_id>;
@ -207,6 +208,46 @@ lbool dl_interface::query(::expr * query) {
_d->rpfp->AssertAxiom(e); _d->rpfp->AssertAxiom(e);
} }
// make sure each predicate is the head of at least one clause
func_decl_set heads;
for(unsigned i = 0; i < clauses.size(); i++){
expr cl = clauses[i];
while(true){
if(cl.is_app()){
decl_kind k = cl.decl().get_decl_kind();
if(k == Implies)
cl = cl.arg(1);
else {
heads.insert(cl.decl());
break;
}
}
else if(cl.is_quantifier())
cl = cl.body();
else break;
}
}
ast_ref_vector const &pinned = m_ctx.get_pinned();
for(unsigned i = 0; i < pinned.size(); i++){
::ast *fa = pinned[i];
if(is_func_decl(fa)){
::func_decl *fd = to_func_decl(fa);
if(m_ctx.is_predicate(fd)) {
func_decl f(_d->ctx,fd);
if(!heads.contains(fd)){
int arity = f.arity();
std::vector<expr> args;
for(int j = 0; j < arity; j++)
args.push_back(_d->ctx.fresh_func_decl("X",f.domain(j))());
expr c = implies(_d->ctx.bool_val(false),f(args));
c = _d->ctx.make_quant(Forall,args,c);
clauses.push_back(c);
}
}
}
}
// creates 1-1 map between clauses and rpfp edges // creates 1-1 map between clauses and rpfp edges
_d->rpfp->FromClauses(clauses); _d->rpfp->FromClauses(clauses);
@ -265,7 +306,19 @@ lbool dl_interface::query(::expr * query) {
// dealloc(rs); this is now owned by data // dealloc(rs); this is now owned by data
// true means the RPFP problem is SAT, so the query is UNSAT // true means the RPFP problem is SAT, so the query is UNSAT
return ans ? l_false : l_true; // but we return undef if the UNSAT result is bounded
if(ans){
if(rs->IsResultRecursionBounded()){
#if 0
m_ctx.set_status(datalog::BOUNDED);
return l_undef;
#else
return l_false;
#endif
}
return l_false;
}
return l_true;
} }
expr_ref dl_interface::get_cover_delta(int level, ::func_decl* pred_orig) { expr_ref dl_interface::get_cover_delta(int level, ::func_decl* pred_orig) {

View file

@ -252,6 +252,11 @@ public:
print_certificate(ctx); print_certificate(ctx);
break; break;
case l_undef: case l_undef:
if(dlctx.get_status() == datalog::BOUNDED){
ctx.regular_stream() << "bounded\n";
print_certificate(ctx);
break;
}
ctx.regular_stream() << "unknown\n"; ctx.regular_stream() << "unknown\n";
switch(dlctx.get_status()) { switch(dlctx.get_status()) {
case datalog::INPUT_ERROR: case datalog::INPUT_ERROR:

View file

@ -736,6 +736,11 @@ namespace pdr {
m_closed = true; m_closed = true;
} }
void model_node::reopen() {
SASSERT(m_closed);
m_closed = false;
}
static bool is_ini(datalog::rule const& r) { static bool is_ini(datalog::rule const& r) {
return r.get_uninterpreted_tail_size() == 0; return r.get_uninterpreted_tail_size() == 0;
} }
@ -745,6 +750,7 @@ namespace pdr {
return const_cast<datalog::rule*>(m_rule); return const_cast<datalog::rule*>(m_rule);
} }
// only initial states are not set by the PDR search. // only initial states are not set by the PDR search.
SASSERT(m_model.get());
datalog::rule const& rl1 = pt().find_rule(*m_model); datalog::rule const& rl1 = pt().find_rule(*m_model);
if (is_ini(rl1)) { if (is_ini(rl1)) {
set_rule(&rl1); set_rule(&rl1);
@ -864,9 +870,10 @@ namespace pdr {
} }
void model_search::add_leaf(model_node& n) { void model_search::add_leaf(model_node& n) {
unsigned& count = cache(n).insert_if_not_there2(n.state(), 0)->get_data().m_value; model_nodes ns;
++count; model_nodes& nodes = cache(n).insert_if_not_there2(n.state(), ns)->get_data().m_value;
if (count == 1 || is_repeated(n)) { nodes.push_back(&n);
if (nodes.size() == 1 || is_repeated(n)) {
set_leaf(n); set_leaf(n);
} }
else { else {
@ -875,7 +882,7 @@ namespace pdr {
} }
void model_search::set_leaf(model_node& n) { void model_search::set_leaf(model_node& n) {
erase_children(n); erase_children(n, true);
SASSERT(n.is_open()); SASSERT(n.is_open());
enqueue_leaf(n); enqueue_leaf(n);
} }
@ -897,7 +904,7 @@ namespace pdr {
set_leaf(*root); set_leaf(*root);
} }
obj_map<expr, unsigned>& model_search::cache(model_node const& n) { obj_map<expr, ptr_vector<model_node> >& model_search::cache(model_node const& n) {
unsigned l = n.orig_level(); unsigned l = n.orig_level();
if (l >= m_cache.size()) { if (l >= m_cache.size()) {
m_cache.resize(l + 1); m_cache.resize(l + 1);
@ -905,7 +912,7 @@ namespace pdr {
return m_cache[l]; return m_cache[l];
} }
void model_search::erase_children(model_node& n) { void model_search::erase_children(model_node& n, bool backtrack) {
ptr_vector<model_node> todo, nodes; ptr_vector<model_node> todo, nodes;
todo.append(n.children()); todo.append(n.children());
erase_leaf(n); erase_leaf(n);
@ -916,13 +923,20 @@ namespace pdr {
nodes.push_back(m); nodes.push_back(m);
todo.append(m->children()); todo.append(m->children());
erase_leaf(*m); erase_leaf(*m);
remove_node(*m); remove_node(*m, backtrack);
} }
std::for_each(nodes.begin(), nodes.end(), delete_proc<model_node>()); std::for_each(nodes.begin(), nodes.end(), delete_proc<model_node>());
} }
void model_search::remove_node(model_node& n) { void model_search::remove_node(model_node& n, bool backtrack) {
if (0 == --cache(n).find(n.state())) { model_nodes& nodes = cache(n).find(n.state());
nodes.erase(&n);
if (nodes.size() > 0 && n.is_open() && backtrack) {
for (unsigned i = 0; i < nodes.size(); ++i) {
nodes[i]->reopen();
}
}
if (nodes.empty()) {
cache(n).remove(n.state()); cache(n).remove(n.state());
} }
} }
@ -1203,8 +1217,8 @@ namespace pdr {
void model_search::reset() { void model_search::reset() {
if (m_root) { if (m_root) {
erase_children(*m_root); erase_children(*m_root, false);
remove_node(*m_root); remove_node(*m_root, false);
dealloc(m_root); dealloc(m_root);
m_root = 0; m_root = 0;
} }
@ -1240,7 +1254,7 @@ namespace pdr {
m_pm(m_fparams, params.max_num_contexts(), m), m_pm(m_fparams, params.max_num_contexts(), m),
m_query_pred(m), m_query_pred(m),
m_query(0), m_query(0),
m_search(m_params.bfs_model_search()), m_search(m_params.bfs_model_search(), m),
m_last_result(l_undef), m_last_result(l_undef),
m_inductive_lvl(0), m_inductive_lvl(0),
m_expanded_lvl(0), m_expanded_lvl(0),

View file

@ -231,6 +231,7 @@ namespace pdr {
} }
void set_closed(); void set_closed();
void reopen();
void set_pre_closed() { m_closed = true; } void set_pre_closed() { m_closed = true; }
void reset() { m_children.reset(); } void reset() { m_children.reset(); }
@ -243,19 +244,21 @@ namespace pdr {
}; };
class model_search { class model_search {
typedef ptr_vector<model_node> model_nodes;
ast_manager& m;
bool m_bfs; bool m_bfs;
model_node* m_root; model_node* m_root;
std::deque<model_node*> m_leaves; std::deque<model_node*> m_leaves;
vector<obj_map<expr, unsigned> > m_cache; vector<obj_map<expr, model_nodes > > m_cache;
obj_map<expr, unsigned>& cache(model_node const& n); obj_map<expr, model_nodes>& cache(model_node const& n);
void erase_children(model_node& n); void erase_children(model_node& n, bool backtrack);
void erase_leaf(model_node& n); void erase_leaf(model_node& n);
void remove_node(model_node& n); void remove_node(model_node& n, bool backtrack);
void enqueue_leaf(model_node& n); // add leaf to priority queue. void enqueue_leaf(model_node& n); // add leaf to priority queue.
void update_models(); void update_models();
public: public:
model_search(bool bfs): m_bfs(bfs), m_root(0) {} model_search(bool bfs, ast_manager& m): m(m), m_bfs(bfs), m_root(0) {}
~model_search(); ~model_search();
void reset(); void reset();