3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

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

Conflicts:
	src/muz_qe/dl_mk_karr_invariants.cpp
This commit is contained in:
Nikolaj Bjorner 2013-04-01 14:57:15 -07:00
commit cbb4c12191
18 changed files with 1116 additions and 642 deletions

View file

@ -233,6 +233,7 @@ namespace datalog {
symbol const& get_name() const { return m_name; } symbol const& get_name() const { return m_name; }
virtual void set_cancel(bool f) {}
relation_manager & get_manager() const { return m_manager; } relation_manager & get_manager() const { return m_manager; }
ast_manager& get_ast_manager() const { return datalog::get_ast_manager_from_rel_manager(m_manager); } ast_manager& get_ast_manager() const { return datalog::get_ast_manager_from_rel_manager(m_manager); }

View file

@ -1028,21 +1028,23 @@ namespace datalog {
func_decl * head_pred = *preds.begin(); func_decl * head_pred = *preds.begin();
const rule_vector & rules = m_rule_set.get_predicate_rules(head_pred); const rule_vector & rules = m_rule_set.get_predicate_rules(head_pred);
reg_idx output_delta; reg_idx output_delta;
if(!output_deltas.find(head_pred, output_delta)) { if (!output_deltas.find(head_pred, output_delta)) {
output_delta = execution_context::void_register; output_delta = execution_context::void_register;
} }
rule_vector::const_iterator it = rules.begin(); rule_vector::const_iterator it = rules.begin();
rule_vector::const_iterator end = rules.end(); rule_vector::const_iterator end = rules.end();
for(; it!=end; ++it) { for (; it != end; ++it) {
rule * r = *it; rule * r = *it;
SASSERT(r->get_head()->get_decl()==head_pred); SASSERT(r->get_head()->get_decl()==head_pred);
compile_rule_evaluation(r, input_deltas, output_delta, false, acc); compile_rule_evaluation(r, input_deltas, output_delta, false, acc);
} }
if(add_saturation_marks) { if (add_saturation_marks) {
//now the predicate is saturated, so we may mark it as such //now the predicate is saturated, so we may mark it as such
acc.push_back(instruction::mk_mark_saturated(m_context.get_manager(), head_pred)); acc.push_back(instruction::mk_mark_saturated(m_context.get_manager(), head_pred));
} }
@ -1068,7 +1070,7 @@ namespace datalog {
for(; sit!=send; ++sit) { for(; sit!=send; ++sit) {
func_decl_set & strat_preds = **sit; func_decl_set & strat_preds = **sit;
if(all_saturated(strat_preds)) { if (all_saturated(strat_preds)) {
//all predicates in stratum are saturated, so no need to compile rules for them //all predicates in stratum are saturated, so no need to compile rules for them
continue; continue;
} }
@ -1084,7 +1086,7 @@ namespace datalog {
tout << "\n"; tout << "\n";
); );
if(is_nonrecursive_stratum(strat_preds)) { if (is_nonrecursive_stratum(strat_preds)) {
//this stratum contains just a single non-recursive rule //this stratum contains just a single non-recursive rule
compile_nonrecursive_stratum(strat_preds, input_deltas, output_deltas, add_saturation_marks, acc); compile_nonrecursive_stratum(strat_preds, input_deltas, output_deltas, add_saturation_marks, acc);
} }

View file

@ -954,6 +954,7 @@ namespace datalog {
if (m_pdr.get()) m_pdr->cancel(); if (m_pdr.get()) m_pdr->cancel();
if (m_bmc.get()) m_bmc->cancel(); if (m_bmc.get()) m_bmc->cancel();
if (m_tab.get()) m_tab->cancel(); if (m_tab.get()) m_tab->cancel();
if (m_rel.get()) m_rel->set_cancel(true);
} }
void context::cleanup() { void context::cleanup() {
@ -962,6 +963,7 @@ namespace datalog {
if (m_pdr.get()) m_pdr->cleanup(); if (m_pdr.get()) m_pdr->cleanup();
if (m_bmc.get()) m_bmc->cleanup(); if (m_bmc.get()) m_bmc->cleanup();
if (m_tab.get()) m_tab->cleanup(); if (m_tab.get()) m_tab->cleanup();
if (m_rel.get()) m_rel->set_cancel(false);
} }
class context::engine_type_proc { class context::engine_type_proc {
@ -1231,7 +1233,7 @@ namespace datalog {
return m_rel->result_contains_fact(f); return m_rel->result_contains_fact(f);
} }
// TBD: algebraic data-types declarations will not be printed. // NB: algebraic data-types declarations will not be printed.
class free_func_visitor { class free_func_visitor {
ast_manager& m; ast_manager& m;
func_decl_set m_funcs; func_decl_set m_funcs;

View file

@ -21,6 +21,7 @@ Revision History:
#include "optional.h" #include "optional.h"
#include "ast_pp.h" #include "ast_pp.h"
#include "dl_interval_relation.h" #include "dl_interval_relation.h"
#include "bool_rewriter.h"
namespace datalog { namespace datalog {
@ -30,8 +31,7 @@ namespace datalog {
interval_relation_plugin::interval_relation_plugin(relation_manager& m): interval_relation_plugin::interval_relation_plugin(relation_manager& m):
relation_plugin(interval_relation_plugin::get_name(), m), relation_plugin(interval_relation_plugin::get_name(), m),
m_empty(m_dep), m_empty(m_dep),
m_arith(get_ast_manager()), m_arith(get_ast_manager()) {
m_bsimp(get_ast_manager()) {
} }
bool interval_relation_plugin::can_handle_signature(const relation_signature & sig) { bool interval_relation_plugin::can_handle_signature(const relation_signature & sig) {
@ -374,7 +374,6 @@ namespace datalog {
void interval_relation::to_formula(expr_ref& fml) const { void interval_relation::to_formula(expr_ref& fml) const {
ast_manager& m = get_plugin().get_ast_manager(); ast_manager& m = get_plugin().get_ast_manager();
arith_util& arith = get_plugin().m_arith; arith_util& arith = get_plugin().m_arith;
basic_simplifier_plugin& bsimp = get_plugin().m_bsimp;
expr_ref_vector conjs(m); expr_ref_vector conjs(m);
relation_signature const& sig = get_signature(); relation_signature const& sig = get_signature();
for (unsigned i = 0; i < sig.size(); ++i) { for (unsigned i = 0; i < sig.size(); ++i) {
@ -405,7 +404,8 @@ namespace datalog {
} }
} }
} }
bsimp.mk_and(conjs.size(), conjs.c_ptr(), fml); bool_rewriter br(m);
br.mk_and(conjs.size(), conjs.c_ptr(), fml);
} }

View file

@ -34,7 +34,6 @@ namespace datalog {
v_dependency_manager m_dep; v_dependency_manager m_dep;
interval m_empty; interval m_empty;
arith_util m_arith; arith_util m_arith;
basic_simplifier_plugin m_bsimp;
class join_fn; class join_fn;
class project_fn; class project_fn;

View file

@ -296,18 +296,40 @@ namespace datalog {
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
proof_ref & result_pr) proof_ref & result_pr)
{ {
if (m.is_not(f)) {
if (m.is_not(f) && (m.is_and(args[0]) || m.is_or(args[0]))) {
SASSERT(num==1); SASSERT(num==1);
if (m.is_and(args[0]) || m.is_or(args[0])) { expr_ref tmp(m);
expr_ref e(m.mk_not(args[0]),m); app* a = to_app(args[0]);
if (push_toplevel_junction_negation_inside(e)) { m_app_args.reset();
result = e; for (unsigned i = 0; i < a->get_num_args(); ++i) {
return BR_REWRITE2; m_brwr.mk_not(a->get_arg(i), tmp);
} m_app_args.push_back(tmp);
} }
if (m.is_and(args[0])) {
result = m.mk_or(m_app_args.size(), m_app_args.c_ptr());
}
else {
result = m.mk_and(m_app_args.size(), m_app_args.c_ptr());
}
return BR_REWRITE2;
}
if (!m.is_and(f) && !m.is_or(f)) {
return BR_FAILED;
}
if (num == 0) {
if (m.is_and(f)) {
result = m.mk_true();
}
else {
result = m.mk_false();
}
return BR_DONE;
}
if (num == 1) {
result = args[0];
return BR_DONE;
} }
if (!m.is_and(f) && !m.is_or(f)) { return BR_FAILED; }
if (num<2) { return BR_FAILED; }
m_app_args.reset(); m_app_args.reset();
m_app_args.append(num, args); m_app_args.append(num, args);
@ -318,30 +340,18 @@ namespace datalog {
bool have_rewritten_args = false; bool have_rewritten_args = false;
if (m.is_or(f) || m.is_and(f)) { have_rewritten_args = detect_equivalences(m_app_args, m.is_or(f));
have_rewritten_args = detect_equivalences(m_app_args, m.is_or(f));
#if 0
if (have_rewritten_args) {
std::sort(m_app_args.c_ptr(), m_app_args.c_ptr()+m_app_args.size(), m_expr_cmp);
app_ref orig(m.mk_app(f, num, args),m);
app_ref res(m.mk_app(f, m_app_args.size(), m_app_args.c_ptr()),m);
std::cout<<"s:"<<mk_pp(orig, m)<<"\n";
std::cout<<"t:"<<mk_pp(res, m)<<"\n";
}
#endif
}
if (m_app_args.size()==1) { if (m_app_args.size()==1) {
result = m_app_args[0].get(); result = m_app_args[0].get();
} }
else { else {
if (m.is_and(f)) { if (m.is_and(f)) {
m_brwr.mk_and(m_app_args.size(), m_app_args.c_ptr(), result); result = m.mk_and(m_app_args.size(), m_app_args.c_ptr());
} }
else { else {
SASSERT(m.is_or(f)); SASSERT(m.is_or(f));
m_brwr.mk_or(m_app_args.size(), m_app_args.c_ptr(), result); result = m.mk_or(m_app_args.size(), m_app_args.c_ptr());
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -30,41 +30,32 @@ namespace datalog {
/** /**
\brief Rule transformer that strengthens bodies with invariants. \brief Rule transformer that strengthens bodies with invariants.
*/ */
struct matrix {
vector<vector<rational> > A;
vector<rational> b;
svector<bool> eq;
unsigned size() const { return A.size(); }
void reset() { A.reset(); b.reset(); eq.reset(); }
matrix& operator=(matrix const& other);
void append(matrix const& other) { A.append(other.A); b.append(other.b); eq.append(other.eq); }
void display(std::ostream& out) const;
static void display_row(
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
static void display_ineq(
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
};
class mk_karr_invariants : public rule_transformer::plugin { class mk_karr_invariants : public rule_transformer::plugin {
struct matrix {
vector<vector<rational> > A;
vector<rational> b;
svector<bool> eq;
unsigned size() const { return A.size(); }
void reset() { A.reset(); b.reset(); eq.reset(); }
matrix& operator=(matrix const& other);
void append(matrix const& other) { A.append(other.A); b.append(other.b); eq.append(other.eq); }
void display(std::ostream& out) const;
static void display_row(
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
static void display_ineq(
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
};
class add_invariant_model_converter; class add_invariant_model_converter;
context& m_ctx; context& m_ctx;
ast_manager& m; ast_manager& m;
rule_manager& rm; rule_manager& rm;
context m_inner_ctx;
arith_util a; arith_util a;
obj_map<func_decl, matrix*> m_constraints; void update_body(rel_context& rctx, rule_set& result, rule& r);
obj_map<func_decl, matrix*> m_dual_constraints;
hilbert_basis m_hb;
bool is_linear(expr* e, vector<rational>& row, rational& b, rational const& mul);
bool is_eq(expr* e, var*& v, rational& n);
bool get_transition_relation(rule const& r, matrix& M);
void intersect_matrix(app* p, matrix const& Mp, unsigned num_columns, matrix& M);
matrix* get_constraints(func_decl* p);
matrix& get_dual_constraints(func_decl* p);
void dualizeH(matrix& dst, matrix const& src);
void dualizeI(matrix& dst, matrix const& src);
void update_body(rule_set& rules, rule& r);
public: public:
mk_karr_invariants(context & ctx, unsigned priority); mk_karr_invariants(context & ctx, unsigned priority);
@ -77,6 +68,68 @@ namespace datalog {
}; };
class karr_relation;
class karr_relation_plugin : public relation_plugin {
arith_util a;
hilbert_basis m_hb;
class join_fn;
class project_fn;
class rename_fn;
class union_fn;
class filter_equal_fn;
class filter_identical_fn;
class filter_interpreted_fn;
friend class karr_relation;
public:
karr_relation_plugin(relation_manager& rm):
relation_plugin(karr_relation_plugin::get_name(), rm),
a(get_ast_manager())
{}
virtual bool can_handle_signature(const relation_signature & sig) {
for (unsigned i = 0; i < sig.size(); ++i) {
if (a.is_int(sig[i])) {
return true;
}
}
return false;
}
static symbol get_name() { return symbol("karr_relation"); }
virtual void set_cancel(bool f);
virtual relation_base * mk_empty(const relation_signature & s);
virtual relation_base * mk_full(func_decl* p, const relation_signature & s);
static karr_relation& get(relation_base& r);
static karr_relation const & get(relation_base const& r);
virtual relation_join_fn * mk_join_fn(
const relation_base & t1, const relation_base & t2,
unsigned col_cnt, const unsigned * cols1, const unsigned * cols2);
virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt,
const unsigned * removed_cols);
virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len,
const unsigned * permutation_cycle);
virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src,
const relation_base * delta);
virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt,
const unsigned * identical_cols);
virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value,
unsigned col);
virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition);
private:
bool dualizeI(matrix& dst, matrix const& src);
void dualizeH(matrix& dst, matrix const& src);
};
}; };
#endif /* _DL_MK_KARR_INVARIANTS_H_ */ #endif /* _DL_MK_KARR_INVARIANTS_H_ */

View file

@ -468,6 +468,12 @@ namespace datalog {
} }
} }
void relation_manager::set_cancel(bool f) {
for (unsigned i = 0; i < m_relation_plugins.size(); ++i) {
m_relation_plugins[i]->set_cancel(f);
}
}
std::string relation_manager::to_nice_string(const relation_element & el) const { std::string relation_manager::to_nice_string(const relation_element & el) const {
uint64 val; uint64 val;
std::stringstream stm; std::stringstream stm;

View file

@ -223,6 +223,7 @@ namespace datalog {
relation_fact & to); relation_fact & to);
void set_cancel(bool f);
// ----------------------------------- // -----------------------------------

View file

@ -30,17 +30,17 @@ namespace datalog {
rule_dependencies::rule_dependencies(const rule_dependencies & o, bool reversed): rule_dependencies::rule_dependencies(const rule_dependencies & o, bool reversed):
m_context(o.m_context) { m_context(o.m_context) {
if(reversed) { if (reversed) {
iterator oit = o.begin(); iterator oit = o.begin();
iterator oend = o.end(); iterator oend = o.end();
for(; oit!=oend; ++oit) { for (; oit!=oend; ++oit) {
func_decl * pred = oit->m_key; func_decl * pred = oit->m_key;
item_set & orig_items = *oit->get_value(); item_set & orig_items = *oit->get_value();
ensure_key(pred); ensure_key(pred);
item_set::iterator dit = orig_items.begin(); item_set::iterator dit = orig_items.begin();
item_set::iterator dend = orig_items.end(); item_set::iterator dend = orig_items.end();
for(; dit!=dend; ++dit) { for (; dit!=dend; ++dit) {
func_decl * master_pred = *dit; func_decl * master_pred = *dit;
insert(master_pred, pred); insert(master_pred, pred);
} }
@ -49,7 +49,7 @@ namespace datalog {
else { else {
iterator oit = o.begin(); iterator oit = o.begin();
iterator oend = o.end(); iterator oend = o.end();
for(; oit!=oend; ++oit) { for (; oit!=oend; ++oit) {
func_decl * pred = oit->m_key; func_decl * pred = oit->m_key;
item_set & orig_items = *oit->get_value(); item_set & orig_items = *oit->get_value();
m_data.insert(pred, alloc(item_set, orig_items)); m_data.insert(pred, alloc(item_set, orig_items));
@ -73,7 +73,7 @@ namespace datalog {
rule_dependencies::item_set & rule_dependencies::ensure_key(func_decl * pred) { rule_dependencies::item_set & rule_dependencies::ensure_key(func_decl * pred) {
deps_type::obj_map_entry * e = m_data.insert_if_not_there2(pred, 0); deps_type::obj_map_entry * e = m_data.insert_if_not_there2(pred, 0);
if(!e->get_data().m_value) { if (!e->get_data().m_value) {
e->get_data().m_value = alloc(item_set); e->get_data().m_value = alloc(item_set);
} }
return *e->get_data().m_value; return *e->get_data().m_value;
@ -101,12 +101,13 @@ namespace datalog {
void rule_dependencies::populate(unsigned n, rule * const * rules) { void rule_dependencies::populate(unsigned n, rule * const * rules) {
SASSERT(m_data.empty()); SASSERT(m_data.empty());
for(unsigned i=0; i<n; i++) { for (unsigned i=0; i<n; i++) {
populate(rules[i]); populate(rules[i]);
} }
} }
void rule_dependencies::populate(rule const* r) { void rule_dependencies::populate(rule const* r) {
TRACE("dl_verbose", tout << r->get_decl()->get_name() << "\n";);
m_visited.reset(); m_visited.reset();
func_decl * d = r->get_head()->get_decl(); func_decl * d = r->get_head()->get_decl();
func_decl_set & s = ensure_key(d); func_decl_set & s = ensure_key(d);
@ -141,7 +142,7 @@ namespace datalog {
const rule_dependencies::item_set & rule_dependencies::get_deps(func_decl * f) const { const rule_dependencies::item_set & rule_dependencies::get_deps(func_decl * f) const {
deps_type::obj_map_entry * e = m_data.find_core(f); deps_type::obj_map_entry * e = m_data.find_core(f);
if(!e) { if (!e) {
return m_empty_item_set; return m_empty_item_set;
} }
SASSERT(e->get_data().get_value()); SASSERT(e->get_data().get_value());
@ -152,9 +153,9 @@ namespace datalog {
ptr_vector<func_decl> to_remove; ptr_vector<func_decl> to_remove;
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit!=pend; ++pit) {
func_decl * pred = pit->m_key; func_decl * pred = pit->m_key;
if(!allowed.contains(pred)) { if (!allowed.contains(pred)) {
to_remove.insert(pred); to_remove.insert(pred);
continue; continue;
} }
@ -163,7 +164,7 @@ namespace datalog {
} }
ptr_vector<func_decl>::iterator rit = to_remove.begin(); ptr_vector<func_decl>::iterator rit = to_remove.begin();
ptr_vector<func_decl>::iterator rend = to_remove.end(); ptr_vector<func_decl>::iterator rend = to_remove.end();
for(; rit!=rend; ++rit) { for (; rit!=rend; ++rit) {
remove_m_data_entry(*rit); remove_m_data_entry(*rit);
} }
} }
@ -172,7 +173,7 @@ namespace datalog {
remove_m_data_entry(itm); remove_m_data_entry(itm);
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit!=pend; ++pit) {
item_set & itms = *pit->get_value(); item_set & itms = *pit->get_value();
itms.remove(itm); itms.remove(itm);
} }
@ -181,12 +182,12 @@ namespace datalog {
void rule_dependencies::remove(const item_set & to_remove) { void rule_dependencies::remove(const item_set & to_remove) {
item_set::iterator rit = to_remove.begin(); item_set::iterator rit = to_remove.begin();
item_set::iterator rend = to_remove.end(); item_set::iterator rend = to_remove.end();
for(; rit!=rend; ++rit) { for (; rit!=rend; ++rit) {
remove_m_data_entry(*rit); remove_m_data_entry(*rit);
} }
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit!=pend; ++pit) {
item_set * itms = pit->get_value(); item_set * itms = pit->get_value();
set_difference(*itms, to_remove); set_difference(*itms, to_remove);
} }
@ -196,9 +197,9 @@ namespace datalog {
unsigned res = 0; unsigned res = 0;
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit!=pend; ++pit) {
item_set & itms = *pit->get_value(); item_set & itms = *pit->get_value();
if(itms.contains(f)) { if (itms.contains(f)) {
res++; res++;
} }
} }
@ -214,10 +215,10 @@ namespace datalog {
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit!=pend; ++pit) {
func_decl * pred = pit->m_key; func_decl * pred = pit->m_key;
unsigned deg = in_degree(pred); unsigned deg = in_degree(pred);
if(deg==0) { if (deg==0) {
res.push_back(pred); res.push_back(pred);
} }
else { else {
@ -225,25 +226,25 @@ namespace datalog {
} }
} }
while(curr_index<res.size()) { //res.size() can change in the loop iteration while (curr_index<res.size()) { //res.size() can change in the loop iteration
func_decl * curr = res[curr_index]; func_decl * curr = res[curr_index];
const item_set & children = reversed.get_deps(curr); const item_set & children = reversed.get_deps(curr);
item_set::iterator cit = children.begin(); item_set::iterator cit = children.begin();
item_set::iterator cend = children.end(); item_set::iterator cend = children.end();
for(; cit!=cend; ++cit) { for (; cit!=cend; ++cit) {
func_decl * child = *cit; func_decl * child = *cit;
deg_map::obj_map_entry * e = degs.find_core(child); deg_map::obj_map_entry * e = degs.find_core(child);
SASSERT(e); SASSERT(e);
unsigned & child_deg = e->get_data().m_value; unsigned & child_deg = e->get_data().m_value;
SASSERT(child_deg>0); SASSERT(child_deg>0);
child_deg--; child_deg--;
if(child_deg==0) { if (child_deg==0) {
res.push_back(child); res.push_back(child);
} }
} }
curr_index++; curr_index++;
} }
if(res.size()<init_len+m_data.size()) { if (res.size()<init_len+m_data.size()) {
res.shrink(init_len); res.shrink(init_len);
return false; return false;
} }
@ -251,21 +252,21 @@ namespace datalog {
return true; return true;
} }
void rule_dependencies::display( std::ostream & out ) const void rule_dependencies::display(std::ostream & out ) const
{ {
iterator pit = begin(); iterator pit = begin();
iterator pend = end(); iterator pend = end();
for(; pit!=pend; ++pit) { for (; pit != pend; ++pit) {
func_decl * pred = pit->m_key; func_decl * pred = pit->m_key;
const item_set & deps = *pit->m_value; const item_set & deps = *pit->m_value;
item_set::iterator dit=deps.begin(); item_set::iterator dit=deps.begin();
item_set::iterator dend=deps.end(); item_set::iterator dend=deps.end();
if(dit==dend) { if (dit == dend) {
out<<pred->get_name()<<" - <none>\n"; out<<pred->get_name()<<" - <none>\n";
} }
for(; dit!=dend; ++dit) { for (; dit != dend; ++dit) {
func_decl * dep = *dit; func_decl * dep = *dit;
out<<pred->get_name()<<" -> "<<dep->get_name()<<"\n"; out << pred->get_name() << " -> " << dep->get_name() << "\n";
} }
} }
} }
@ -292,8 +293,8 @@ namespace datalog {
m_deps(rs.m_context), m_deps(rs.m_context),
m_stratifier(0) { m_stratifier(0) {
add_rules(rs); add_rules(rs);
if(rs.m_stratifier) { if (rs.m_stratifier) {
TRUSTME(close()); VERIFY(close());
} }
} }
@ -302,7 +303,7 @@ namespace datalog {
} }
void rule_set::reset() { void rule_set::reset() {
if(m_stratifier) { if (m_stratifier) {
m_stratifier = 0; m_stratifier = 0;
} }
reset_dealloc_values(m_head2rules); reset_dealloc_values(m_head2rules);
@ -346,18 +347,19 @@ namespace datalog {
void rule_set::ensure_closed() void rule_set::ensure_closed()
{ {
if(!is_closed()) { if (!is_closed()) {
TRUSTME(close()); VERIFY(close());
} }
} }
bool rule_set::close() { bool rule_set::close() {
SASSERT(!is_closed()); //the rule_set is not already closed SASSERT(!is_closed()); //the rule_set is not already closed
m_deps.populate(*this); m_deps.populate(*this);
m_stratifier = alloc(rule_stratifier, m_deps); m_stratifier = alloc(rule_stratifier, m_deps);
if(!stratified_negation()) { if (!stratified_negation()) {
m_stratifier = 0; m_stratifier = 0;
m_deps.reset(); m_deps.reset();
return false; return false;
@ -391,7 +393,7 @@ namespace datalog {
unsigned head_strat = get_predicate_strat(head_decl); unsigned head_strat = get_predicate_strat(head_decl);
SASSERT(head_strat>=neg_strat); //head strat can never be lower than that of a tail SASSERT(head_strat>=neg_strat); //head strat can never be lower than that of a tail
if(head_strat==neg_strat) { if (head_strat == neg_strat) {
return false; return false;
} }
} }
@ -415,7 +417,7 @@ namespace datalog {
const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const { const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const {
decl2rules::obj_map_entry * e = m_head2rules.find_core(pred); decl2rules::obj_map_entry * e = m_head2rules.find_core(pred);
if(!e) { if (!e) {
return m_empty_rule_vector; return m_empty_rule_vector;
} }
return *e->get_data().m_value; return *e->get_data().m_value;
@ -443,7 +445,7 @@ namespace datalog {
ptr_vector<rule>::iterator end2 = rules->end(); ptr_vector<rule>::iterator end2 = rules->end();
for (; it2 != end2; ++it2) { for (; it2 != end2; ++it2) {
rule * r = *it2; rule * r = *it2;
if(!r->passes_output_thresholds(m_context)) { if (!r->passes_output_thresholds(m_context)) {
continue; continue;
} }
r->display(m_context, out); r->display(m_context, out);
@ -468,23 +470,23 @@ namespace datalog {
const pred_set_vector & strats = get_strats(); const pred_set_vector & strats = get_strats();
pred_set_vector::const_iterator sit = strats.begin(); pred_set_vector::const_iterator sit = strats.begin();
pred_set_vector::const_iterator send = strats.end(); pred_set_vector::const_iterator send = strats.end();
for(; sit!=send; ++sit) { for (; sit!=send; ++sit) {
func_decl_set & strat = **sit; func_decl_set & strat = **sit;
func_decl_set::iterator fit=strat.begin(); func_decl_set::iterator fit=strat.begin();
func_decl_set::iterator fend=strat.end(); func_decl_set::iterator fend=strat.end();
bool non_empty = false; bool non_empty = false;
for(; fit!=fend; ++fit) { for (; fit!=fend; ++fit) {
func_decl * first = *fit; func_decl * first = *fit;
const func_decl_set & deps = m_deps.get_deps(first); const func_decl_set & deps = m_deps.get_deps(first);
func_decl_set::iterator dit=deps.begin(); func_decl_set::iterator dit=deps.begin();
func_decl_set::iterator dend=deps.end(); func_decl_set::iterator dend=deps.end();
for(; dit!=dend; ++dit) { for (; dit!=dend; ++dit) {
non_empty = true; non_empty = true;
func_decl * dep = *dit; func_decl * dep = *dit;
out<<first->get_name()<<" -> "<<dep->get_name()<<"\n"; out<<first->get_name()<<" -> "<<dep->get_name()<<"\n";
} }
} }
if(non_empty && sit!=send) { if (non_empty && sit!=send) {
out << "\n"; out << "\n";
} }
} }
@ -499,7 +501,7 @@ namespace datalog {
rule_stratifier::~rule_stratifier() { rule_stratifier::~rule_stratifier() {
comp_vector::iterator it = m_strats.begin(); comp_vector::iterator it = m_strats.begin();
comp_vector::iterator end = m_strats.end(); comp_vector::iterator end = m_strats.end();
for(; it!=end; ++it) { for (; it!=end; ++it) {
SASSERT(*it); SASSERT(*it);
dealloc(*it); dealloc(*it);
} }
@ -507,7 +509,7 @@ namespace datalog {
unsigned rule_stratifier::get_predicate_strat(func_decl * pred) const { unsigned rule_stratifier::get_predicate_strat(func_decl * pred) const {
unsigned num; unsigned num;
if(!m_pred_strat_nums.find(pred, num)) { if (!m_pred_strat_nums.find(pred, num)) {
//the number of the predicate is not stored, therefore it did not appear //the number of the predicate is not stored, therefore it did not appear
//in the algorithm and therefore it does not depend on anything and nothing //in the algorithm and therefore it does not depend on anything and nothing
//depends on it. So it is safe to assign zero strate to it, although it is //depends on it. So it is safe to assign zero strate to it, although it is
@ -520,19 +522,19 @@ namespace datalog {
void rule_stratifier::traverse(T* el) { void rule_stratifier::traverse(T* el) {
unsigned p_num; unsigned p_num;
if(m_preorder_nums.find(el, p_num)) { if (m_preorder_nums.find(el, p_num)) {
if(p_num<m_first_preorder) { if (p_num < m_first_preorder) {
//traversed in a previous sweep //traversed in a previous sweep
return; return;
} }
if(m_component_nums.contains(el)) { if (m_component_nums.contains(el)) {
//we already assigned a component for el //we already assigned a component for el
return; return;
} }
while(!m_stack_P.empty()) { while (!m_stack_P.empty()) {
unsigned on_stack_num; unsigned on_stack_num;
TRUSTME( m_preorder_nums.find(m_stack_P.back(), on_stack_num) ); VERIFY( m_preorder_nums.find(m_stack_P.back(), on_stack_num) );
if(on_stack_num <= p_num) { if (on_stack_num <= p_num) {
break; break;
} }
m_stack_P.pop_back(); m_stack_P.pop_back();
@ -548,11 +550,11 @@ namespace datalog {
const item_set & children = m_deps.get_deps(el); const item_set & children = m_deps.get_deps(el);
item_set::iterator cit=children.begin(); item_set::iterator cit=children.begin();
item_set::iterator cend=children.end(); item_set::iterator cend=children.end();
for(; cit!=cend; ++cit) { for (; cit!=cend; ++cit) {
traverse(*cit); traverse(*cit);
} }
if(el==m_stack_P.back()) { if (el == m_stack_P.back()) {
unsigned comp_num = m_components.size(); unsigned comp_num = m_components.size();
item_set * new_comp = alloc(item_set); item_set * new_comp = alloc(item_set);
m_components.push_back(new_comp); m_components.push_back(new_comp);
@ -563,21 +565,21 @@ namespace datalog {
m_stack_S.pop_back(); m_stack_S.pop_back();
new_comp->insert(s_el); new_comp->insert(s_el);
m_component_nums.insert(s_el, comp_num); m_component_nums.insert(s_el, comp_num);
} while(s_el!=el); } while (s_el!=el);
m_stack_P.pop_back(); m_stack_P.pop_back();
} }
} }
} }
void rule_stratifier::process() { void rule_stratifier::process() {
if(m_deps.empty()) { if (m_deps.empty()) {
return; return;
} }
//detect strong components //detect strong components
rule_dependencies::iterator it = m_deps.begin(); rule_dependencies::iterator it = m_deps.begin();
rule_dependencies::iterator end = m_deps.end(); rule_dependencies::iterator end = m_deps.end();
for(; it!=end; ++it) { for (; it!=end; ++it) {
T * el = it->m_key; T * el = it->m_key;
//we take a note of the preorder number with which this sweep started //we take a note of the preorder number with which this sweep started
m_first_preorder = m_next_preorder; m_first_preorder = m_next_preorder;
@ -593,32 +595,32 @@ namespace datalog {
//init in_degrees //init in_degrees
it = m_deps.begin(); it = m_deps.begin();
end = m_deps.end(); end = m_deps.end();
for(; it!=end; ++it) { for (; it != end; ++it) {
T * el = it->m_key; T * el = it->m_key;
item_set * out_edges = it->m_value; item_set * out_edges = it->m_value;
unsigned el_comp; unsigned el_comp;
TRUSTME( m_component_nums.find(el, el_comp) ); VERIFY( m_component_nums.find(el, el_comp) );
item_set::iterator eit=out_edges->begin(); item_set::iterator eit = out_edges->begin();
item_set::iterator eend=out_edges->end(); item_set::iterator eend = out_edges->end();
for(; eit!=eend; ++eit) { for (; eit!=eend; ++eit) {
T * tgt = *eit; T * tgt = *eit;
unsigned tgt_comp = m_component_nums.find(tgt); unsigned tgt_comp = m_component_nums.find(tgt);
if(el_comp!=tgt_comp) { if (el_comp != tgt_comp) {
in_degrees[tgt_comp]++; in_degrees[tgt_comp]++;
} }
} }
} }
//We put components whose indegree is zero to m_strats and assign its // We put components whose indegree is zero to m_strats and assign its
//m_components entry to zero. // m_components entry to zero.
unsigned comp_cnt = m_components.size(); unsigned comp_cnt = m_components.size();
for(unsigned i=0; i<comp_cnt; i++) { for (unsigned i = 0; i < comp_cnt; i++) {
if(in_degrees[i]==0) { if (in_degrees[i] == 0) {
m_strats.push_back(m_components[i]); m_strats.push_back(m_components[i]);
m_components[i] = 0; m_components[i] = 0;
} }
@ -628,33 +630,31 @@ namespace datalog {
//we remove edges from components with zero indegre building the topological ordering //we remove edges from components with zero indegre building the topological ordering
unsigned strats_index = 0; unsigned strats_index = 0;
while(strats_index < m_strats.size()) { //m_strats.size() changes inside the loop! while (strats_index < m_strats.size()) { //m_strats.size() changes inside the loop!
item_set * comp = m_strats[strats_index]; item_set * comp = m_strats[strats_index];
item_set::iterator cit=comp->begin(); item_set::iterator cit=comp->begin();
item_set::iterator cend=comp->end(); item_set::iterator cend=comp->end();
for(; cit!=cend; ++cit) { for (; cit!=cend; ++cit) {
T * el = *cit; T * el = *cit;
const item_set & deps = m_deps.get_deps(el); const item_set & deps = m_deps.get_deps(el);
item_set::iterator eit=deps.begin(); item_set::iterator eit=deps.begin();
item_set::iterator eend=deps.end(); item_set::iterator eend=deps.end();
for(; eit!=eend; ++eit) { for (; eit!=eend; ++eit) {
T * tgt = *eit; T * tgt = *eit;
unsigned tgt_comp; unsigned tgt_comp;
TRUSTME( m_component_nums.find(tgt, tgt_comp) ); VERIFY( m_component_nums.find(tgt, tgt_comp) );
//m_components[tgt_comp]==0 means the edge is intra-component. //m_components[tgt_comp]==0 means the edge is intra-component.
//Otherwise it would go to another component, but it is not possible, since //Otherwise it would go to another component, but it is not possible, since
//as m_components[tgt_comp]==0, its indegree has already reached zero. //as m_components[tgt_comp]==0, its indegree has already reached zero.
if(m_components[tgt_comp]) { if (m_components[tgt_comp]) {
SASSERT(in_degrees[tgt_comp]>0); SASSERT(in_degrees[tgt_comp]>0);
in_degrees[tgt_comp]--; in_degrees[tgt_comp]--;
if(in_degrees[tgt_comp]==0) { if (in_degrees[tgt_comp]==0) {
m_strats.push_back(m_components[tgt_comp]); m_strats.push_back(m_components[tgt_comp]);
m_components[tgt_comp] = 0; m_components[tgt_comp] = 0;
} }
} }
traverse(*cit); traverse(*cit);
} }
} }
@ -669,13 +669,12 @@ namespace datalog {
SASSERT(m_pred_strat_nums.empty()); SASSERT(m_pred_strat_nums.empty());
unsigned strat_cnt = m_strats.size(); unsigned strat_cnt = m_strats.size();
for(unsigned strat_index=0; strat_index<strat_cnt; strat_index++) { for (unsigned strat_index=0; strat_index<strat_cnt; strat_index++) {
item_set * comp = m_strats[strat_index]; item_set * comp = m_strats[strat_index];
item_set::iterator cit=comp->begin(); item_set::iterator cit=comp->begin();
item_set::iterator cend=comp->end(); item_set::iterator cend=comp->end();
for(; cit!=cend; ++cit) { for (; cit != cend; ++cit) {
T * el = *cit; T * el = *cit;
m_pred_strat_nums.insert(el, strat_index); m_pred_strat_nums.insert(el, strat_index);
} }
} }
@ -686,6 +685,21 @@ namespace datalog {
m_stack_P.finalize(); m_stack_P.finalize();
m_component_nums.finalize(); m_component_nums.finalize();
m_components.finalize(); m_components.finalize();
}
void rule_stratifier::display(std::ostream& out) const {
m_deps.display(out << "dependencies\n");
out << "strata\n";
for (unsigned i = 0; i < m_strats.size(); ++i) {
item_set::iterator it = m_strats[i]->begin();
item_set::iterator end = m_strats[i]->end();
for (; it != end; ++it) {
out << (*it)->get_name() << " ";
}
out << "\n";
}
} }
}; };

View file

@ -146,6 +146,8 @@ namespace datalog {
const comp_vector & get_strats() const { return m_strats; } const comp_vector & get_strats() const { return m_strats; }
unsigned get_predicate_strat(func_decl * pred) const; unsigned get_predicate_strat(func_decl * pred) const;
void display( std::ostream & out ) const;
}; };
/** /**

View file

@ -153,35 +153,6 @@ namespace datalog {
flatten_or(result); flatten_or(result);
} }
bool push_toplevel_junction_negation_inside(expr_ref& e)
{
ast_manager& m = e.get_manager();
bool_rewriter brwr(m);
expr * arg;
if(!m.is_not(e, arg)) { return false; }
bool is_and = m.is_and(arg);
if(!is_and && !m.is_or(arg)) { return false; }
//now we know we have formula we need to transform
app * junction = to_app(arg);
expr_ref_vector neg_j_args(m);
unsigned num_args = junction->get_num_args();
for(unsigned i=0; i<num_args; ++i) {
expr_ref neg_j_arg(m);
brwr.mk_not(junction->get_arg(i), neg_j_arg);
neg_j_args.push_back(neg_j_arg);
}
if(is_and) {
brwr.mk_or(neg_j_args.size(), neg_j_args.c_ptr(), e);
}
else {
brwr.mk_and(neg_j_args.size(), neg_j_args.c_ptr(), e);
}
return true;
}
bool contains_var(expr * trm, unsigned var_idx) { bool contains_var(expr * trm, unsigned var_idx) {
ptr_vector<sort> vars; ptr_vector<sort> vars;
::get_free_vars(trm, vars); ::get_free_vars(trm, vars);

View file

@ -81,19 +81,6 @@ namespace datalog {
void flatten_or(expr* fml, expr_ref_vector& result); void flatten_or(expr* fml, expr_ref_vector& result);
/**
Transform
~(a1 | ... | aN)
into
~a1 | ... | ~aN
and
~(a1 & ... & aN)
into
~a1 | ... | ~aN
Return true if something was done.
*/
bool push_toplevel_junction_negation_inside(expr_ref& e);
bool contains_var(expr * trm, unsigned var_idx); bool contains_var(expr * trm, unsigned var_idx);

View file

@ -744,7 +744,6 @@ void hilbert_basis::reset() {
if (m_passive2) { if (m_passive2) {
m_passive2->reset(); m_passive2->reset();
} }
m_cancel = false;
if (m_index) { if (m_index) {
m_index->reset(1); m_index->reset(1);
} }
@ -867,7 +866,7 @@ lbool hilbert_basis::saturate() {
stopwatch sw; stopwatch sw;
sw.start(); sw.start();
lbool r = saturate(m_ineqs[m_current_ineq], m_iseq[m_current_ineq]); lbool r = saturate(m_ineqs[m_current_ineq], m_iseq[m_current_ineq]);
IF_VERBOSE(1, IF_VERBOSE(3,
{ statistics st; { statistics st;
collect_statistics(st); collect_statistics(st);
st.display(verbose_stream()); st.display(verbose_stream());

View file

@ -37,10 +37,13 @@ typedef vector<rational> rational_vector;
class hilbert_basis { class hilbert_basis {
static const bool check = false; static const bool check = true;
typedef checked_int64<check> numeral; typedef checked_int64<check> numeral;
typedef vector<numeral> num_vector; typedef vector<numeral> num_vector;
static checked_int64<check> to_numeral(rational const& r) { static checked_int64<check> to_numeral(rational const& r) {
if (!r.is_int64()) {
throw checked_int64<check>::overflow_exception();
}
return checked_int64<check>(r.get_int64()); return checked_int64<check>(r.get_int64());
} }
static rational to_rational(checked_int64<check> const& i) { static rational to_rational(checked_int64<check> const& i) {

View file

@ -27,6 +27,7 @@ Revision History:
#include"dl_product_relation.h" #include"dl_product_relation.h"
#include"dl_bound_relation.h" #include"dl_bound_relation.h"
#include"dl_interval_relation.h" #include"dl_interval_relation.h"
#include"dl_mk_karr_invariants.h"
#include"dl_finite_product_relation.h" #include"dl_finite_product_relation.h"
#include"dl_sparse_table.h" #include"dl_sparse_table.h"
#include"dl_table.h" #include"dl_table.h"
@ -54,6 +55,8 @@ namespace datalog {
get_rmanager().register_plugin(alloc(bound_relation_plugin, get_rmanager())); get_rmanager().register_plugin(alloc(bound_relation_plugin, get_rmanager()));
get_rmanager().register_plugin(alloc(interval_relation_plugin, get_rmanager())); get_rmanager().register_plugin(alloc(interval_relation_plugin, get_rmanager()));
get_rmanager().register_plugin(alloc(karr_relation_plugin, get_rmanager()));
} }
@ -178,23 +181,23 @@ namespace datalog {
return result; return result;
} }
#define BEGIN_QUERY() \ #define BEGIN_QUERY() \
rule_set original_rules(m_context.get_rules()); \ rule_set original_rules(m_context.get_rules()); \
decl_set original_preds; \ decl_set original_preds; \
m_context.collect_predicates(original_preds); \ m_context.collect_predicates(original_preds); \
bool was_closed = m_context.is_closed(); \ bool was_closed = m_context.is_closed(); \
if (was_closed) { \ if (was_closed) { \
m_context.reopen(); \ m_context.reopen(); \
} \ } \
#define END_QUERY() \ #define END_QUERY() \
m_context.reopen(); \ m_context.reopen(); \
m_context.replace_rules(original_rules); \ m_context.replace_rules(original_rules); \
restrict_predicates(original_preds); \ restrict_predicates(original_preds); \
\ \
if (was_closed) { \ if (was_closed) { \
m_context.close(); \ m_context.close(); \
} \ } \
lbool rel_context::query(unsigned num_rels, func_decl * const* rels) { lbool rel_context::query(unsigned num_rels, func_decl * const* rels) {
get_rmanager().reset_saturated_marks(); get_rmanager().reset_saturated_marks();
@ -427,6 +430,10 @@ namespace datalog {
get_rmanager().set_predicate_kind(pred, target_kind); get_rmanager().set_predicate_kind(pred, target_kind);
} }
void rel_context::set_cancel(bool f) {
get_rmanager().set_cancel(f);
}
relation_plugin & rel_context::get_ordinary_relation_plugin(symbol relation_name) { relation_plugin & rel_context::get_ordinary_relation_plugin(symbol relation_name) {
relation_plugin * plugin = get_rmanager().get_relation_plugin(relation_name); relation_plugin * plugin = get_rmanager().get_relation_plugin(relation_name);
if (!plugin) { if (!plugin) {

View file

@ -63,7 +63,6 @@ namespace datalog {
bool output_profile() const; bool output_profile() const;
lbool query(expr* q); lbool query(expr* q);
lbool query(unsigned num_rels, func_decl * const* rels); lbool query(unsigned num_rels, func_decl * const* rels);
@ -72,6 +71,7 @@ namespace datalog {
void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred); void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred);
void set_cancel(bool f);
/** /**
\brief Restrict the set of used predicates to \c res. \brief Restrict the set of used predicates to \c res.