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

Datalog improvements:

- add cancel status
 - display statistics on cancel
(by me & Nikolaj)

Signed-off-by: Nuno Lopes <t-nclaud@microsoft.com>
This commit is contained in:
Nuno Lopes 2013-03-27 10:38:50 -07:00
parent 25a41d48dc
commit 1cece1c1fb
10 changed files with 142 additions and 77 deletions

View file

@ -234,7 +234,6 @@ public:
catch (z3_exception& ex) { catch (z3_exception& ex) {
ctx.regular_stream() << "(error \"query failed: " << ex.msg() << "\")" << std::endl; ctx.regular_stream() << "(error \"query failed: " << ex.msg() << "\")" << std::endl;
} }
dlctx.cleanup();
} }
switch (status) { switch (status) {
case l_false: case l_false:
@ -250,6 +249,7 @@ public:
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:
ctx.regular_stream() << "input error\n";
break; break;
case datalog::MEMOUT: case datalog::MEMOUT:
@ -261,14 +261,21 @@ public:
break; break;
case datalog::OK: case datalog::OK:
UNREACHABLE();
break;
case datalog::CANCELED:
ctx.regular_stream() << "canceled\n";
dlctx.display_profile(ctx.regular_stream());
break; break;
default: default:
// exception was raised. UNREACHABLE();
break; break;
} }
break; break;
} }
dlctx.cleanup();
print_statistics(ctx); print_statistics(ctx);
m_target = 0; m_target = 0;
} }

View file

@ -229,11 +229,13 @@ namespace datalog {
m_pinned(m), m_pinned(m),
m_vars(m), m_vars(m),
m_rule_set(*this), m_rule_set(*this),
m_transformed_rule_set(*this),
m_rule_fmls(m), m_rule_fmls(m),
m_background(m), m_background(m),
m_mc(0), m_mc(0),
m_closed(false), m_closed(false),
m_saturation_was_run(false), m_saturation_was_run(false),
m_last_status(OK),
m_last_answer(m), m_last_answer(m),
m_engine(LAST_ENGINE), m_engine(LAST_ENGINE),
m_cancel(false) { m_cancel(false) {
@ -873,6 +875,11 @@ namespace datalog {
m_rule_set.add_rules(rs); m_rule_set.add_rules(rs);
} }
void context::record_transformed_rules() {
m_transformed_rule_set.reset();
m_transformed_rule_set.add_rules(m_rule_set);
}
void context::apply_default_transformation() { void context::apply_default_transformation() {
ensure_closed(); ensure_closed();
m_transf.reset(); m_transf.reset();
@ -942,18 +949,18 @@ namespace datalog {
void context::cancel() { void context::cancel() {
m_cancel = true; m_cancel = true;
m_last_status = CANCELED;
m_transf.cancel(); m_transf.cancel();
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_rel.get()) m_rel->cancel();
if (m_tab.get()) m_tab->cancel(); if (m_tab.get()) m_tab->cancel();
} }
void context::cleanup() { void context::cleanup() {
m_cancel = false; m_cancel = false;
m_last_status = OK;
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_rel.get()) m_rel->cleanup();
if (m_tab.get()) m_tab->cleanup(); if (m_tab.get()) m_tab->cleanup();
} }
@ -1178,6 +1185,20 @@ namespace datalog {
} }
} }
void context::display_profile(std::ostream& out) const {
out << "\n---------------\n";
out << "Original rules\n";
display_rules(out);
out << "\n---------------\n";
out << "Transformed rules\n";
m_transformed_rule_set.display(out);
if (m_rel) {
m_rel->display_profile(out);
}
}
void context::reset_statistics() { void context::reset_statistics() {
if (m_pdr) { if (m_pdr) {
m_pdr->reset_statistics(); m_pdr->reset_statistics();

View file

@ -52,7 +52,8 @@ namespace datalog {
OK, OK,
TIMEOUT, TIMEOUT,
MEMOUT, MEMOUT,
INPUT_ERROR INPUT_ERROR,
CANCELED
}; };
class context { class context {
@ -92,6 +93,7 @@ namespace datalog {
sym2decl m_preds_by_name; sym2decl m_preds_by_name;
pred2syms m_argument_var_names; pred2syms m_argument_var_names;
rule_set m_rule_set; rule_set m_rule_set;
rule_set m_transformed_rule_set;
expr_ref_vector m_rule_fmls; expr_ref_vector m_rule_fmls;
svector<symbol> m_rule_names; svector<symbol> m_rule_names;
expr_ref_vector m_background; expr_ref_vector m_background;
@ -323,6 +325,7 @@ namespace datalog {
void transform_rules(); void transform_rules();
void transform_rules(rule_transformer& transf); void transform_rules(rule_transformer& transf);
void replace_rules(rule_set & rs); void replace_rules(rule_set & rs);
void record_transformed_rules();
void apply_default_transformation(); void apply_default_transformation();
@ -349,6 +352,8 @@ namespace datalog {
void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out); void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out);
void display_profile(std::ostream& out) const;
// ----------------------------------- // -----------------------------------
// //
// basic usage methods // basic usage methods
@ -356,6 +361,7 @@ namespace datalog {
// ----------------------------------- // -----------------------------------
void cancel(); void cancel();
bool canceled() const { return m_cancel; }
void cleanup(); void cleanup();
void reset_cancel() { cleanup(); } void reset_cancel() { cleanup(); }

View file

@ -58,14 +58,18 @@ namespace datalog {
reset_timelimit(); reset_timelimit();
} }
rel_context& execution_context::get_rel_context() {
return m_context.get_rel_context();
}
struct compare_size_proc { struct compare_size_proc {
typedef std::pair<unsigned, unsigned> pr; typedef std::pair<unsigned, unsigned> pr;
bool operator()(pr const& a, pr const& b) const { bool operator()(pr const& a, pr const& b) const {
return a.second > b.second; return a.second > b.second;
} }
}; };
void execution_context::report_big_relations(unsigned threshold, std::ostream & out) {
void execution_context::report_big_relations(unsigned threshold, std::ostream & out) const {
unsigned n = register_count(); unsigned n = register_count();
svector<std::pair<unsigned, unsigned> > sizes; svector<std::pair<unsigned, unsigned> > sizes;
size_t total_bytes = 0; size_t total_bytes = 0;
@ -110,6 +114,7 @@ namespace datalog {
bool execution_context::should_terminate() { bool execution_context::should_terminate() {
return return
m_context.canceled() ||
memory::above_high_watermark() || memory::above_high_watermark() ||
(m_stopwatch && (m_stopwatch &&
m_timelimit_ms != 0 && m_timelimit_ms != 0 &&
@ -135,7 +140,7 @@ namespace datalog {
process_costs(); process_costs();
} }
void instruction::display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const { void instruction::display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const {
out << indentation; out << indentation;
display_head_impl(ctx, out); display_head_impl(ctx, out);
if (ctx.output_profile()) { if (ctx.output_profile()) {
@ -182,7 +187,7 @@ namespace datalog {
virtual void make_annotations(execution_context & ctx) { virtual void make_annotations(execution_context & ctx) {
ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str()); ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str());
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
const char * rel_name = m_pred->get_name().bare_str(); const char * rel_name = m_pred->get_name().bare_str();
if (m_store) { if (m_store) {
out << "store " << m_reg << " into " << rel_name; out << "store " << m_reg << " into " << rel_name;
@ -213,7 +218,7 @@ namespace datalog {
virtual void make_annotations(execution_context & ctx) { virtual void make_annotations(execution_context & ctx) {
ctx.set_register_annotation(m_reg, "alloc"); ctx.set_register_annotation(m_reg, "alloc");
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "dealloc " << m_reg; out << "dealloc " << m_reg;
} }
}; };
@ -248,7 +253,7 @@ namespace datalog {
ctx.set_register_annotation(m_src, str); ctx.set_register_annotation(m_src, str);
} }
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << (m_clone ? "clone " : "move ") << m_src << " into " << m_tgt; out << (m_clone ? "clone " : "move ") << m_src << " into " << m_tgt;
} }
}; };
@ -304,11 +309,11 @@ namespace datalog {
virtual void make_annotations(execution_context & ctx) { virtual void make_annotations(execution_context & ctx) {
m_body->make_annotations(ctx); m_body->make_annotations(ctx);
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
out << "while"; out << "while";
print_container(m_controls, out); print_container(m_controls, out);
} }
virtual void display_body_impl(rel_context & ctx, std::ostream & out, std::string indentation) const { virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const {
m_body->display_indented(ctx, out, indentation+" "); m_body->display_indented(ctx, out, indentation+" ");
} }
}; };
@ -385,7 +390,7 @@ namespace datalog {
ctx.get_register_annotation(m_rel1, a1); ctx.get_register_annotation(m_rel1, a1);
ctx.set_register_annotation(m_res, "join " + a1 + " " + a2); ctx.set_register_annotation(m_res, "join " + a1 + " " + a2);
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
out << "join " << m_rel1; out << "join " << m_rel1;
print_container(m_cols1, out); print_container(m_cols1, out);
out << " and " << m_rel2; out << " and " << m_rel2;
@ -434,7 +439,7 @@ namespace datalog {
a << "filter_equal " << m_col << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); a << "filter_equal " << m_col << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value);
ctx.set_register_annotation(m_reg, a.str()); ctx.set_register_annotation(m_reg, a.str());
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "filter_equal " << m_reg << " col: " << m_col << " val: " out << "filter_equal " << m_reg << " col: " << m_col << " val: "
<< ctx.get_rmanager().to_nice_string(m_value); << ctx.get_rmanager().to_nice_string(m_value);
} }
@ -476,7 +481,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "filter_identical " << m_reg << " "; out << "filter_identical " << m_reg << " ";
print_container(m_cols, out); print_container(m_cols, out);
} }
@ -519,7 +524,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "filter_interpreted " << m_reg << " using " out << "filter_interpreted " << m_reg << " using "
<< mk_pp(m_cond, m_cond.get_manager()); << mk_pp(m_cond, m_cond.get_manager());
} }
@ -619,12 +624,16 @@ namespace datalog {
return true; return true;
} }
virtual void make_annotations(execution_context & ctx) { virtual void make_annotations(execution_context & ctx) {
std::string str; std::string str = "union";
if (ctx.get_register_annotation(m_tgt, str) && m_delta!=execution_context::void_register) { if (!ctx.get_register_annotation(m_tgt, str)) {
ctx.set_register_annotation(m_delta, "delta of "+str); ctx.set_register_annotation(m_tgt, "union");
} }
if (m_delta != execution_context::void_register) {
str = "delta of " + str;
}
ctx.set_register_annotation(m_delta, str);
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << (m_widen ? "widen " : "union ") << m_src << " into " << m_tgt; out << (m_widen ? "widen " : "union ") << m_src << " into " << m_tgt;
if (m_delta!=execution_context::void_register) { if (m_delta!=execution_context::void_register) {
out << " with delta " << m_delta; out << " with delta " << m_delta;
@ -678,7 +687,7 @@ namespace datalog {
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << (m_projection ? "project " : "rename ") << m_src << " into " << m_tgt; out << (m_projection ? "project " : "rename ") << m_src << " into " << m_tgt;
out << (m_projection ? " deleting columns " : " with cycle "); out << (m_projection ? " deleting columns " : " with cycle ");
print_container(m_cols, out); print_container(m_cols, out);
@ -739,7 +748,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "join_project " << m_rel1; out << "join_project " << m_rel1;
print_container(m_cols1, out); print_container(m_cols1, out);
out << " and " << m_rel2; out << " and " << m_rel2;
@ -800,7 +809,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "select_equal_and_project " << m_src <<" into " << m_result << " col: " << m_col out << "select_equal_and_project " << m_src <<" into " << m_result << " col: " << m_col
<< " val: " << ctx.get_rmanager().to_nice_string(m_value); << " val: " << ctx.get_rmanager().to_nice_string(m_value);
} }
@ -854,7 +863,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "filter_by_negation on " << m_tgt; out << "filter_by_negation on " << m_tgt;
print_container(m_cols1, out); print_container(m_cols1, out);
out << " with " << m_neg_rel; out << " with " << m_neg_rel;
@ -892,7 +901,7 @@ namespace datalog {
ctx.set_reg(m_tgt, rel); ctx.set_reg(m_tgt, rel);
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "mk_unary_singleton into " << m_tgt << " sort:" out << "mk_unary_singleton into " << m_tgt << " sort:"
<< ctx.get_rmanager().to_nice_string(m_sig[0]) << " val:" << ctx.get_rmanager().to_nice_string(m_sig[0]) << " val:"
<< ctx.get_rmanager().to_nice_string(m_sig[0], m_fact[0]); << ctx.get_rmanager().to_nice_string(m_sig[0], m_fact[0]);
@ -922,7 +931,7 @@ namespace datalog {
ctx.set_reg(m_tgt, ctx.get_rel_context().get_rmanager().mk_full_relation(m_sig, m_pred)); ctx.set_reg(m_tgt, ctx.get_rel_context().get_rmanager().mk_full_relation(m_sig, m_pred));
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "mk_total into " << m_tgt << " sort:" out << "mk_total into " << m_tgt << " sort:"
<< ctx.get_rmanager().to_nice_string(m_sig); << ctx.get_rmanager().to_nice_string(m_sig);
} }
@ -947,7 +956,7 @@ namespace datalog {
ctx.get_rel_context().get_rmanager().mark_saturated(m_pred); ctx.get_rel_context().get_rmanager().mark_saturated(m_pred);
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "mark_saturated " << m_pred->get_name().bare_str(); out << "mark_saturated " << m_pred->get_name().bare_str();
} }
virtual void make_annotations(execution_context & ctx) { virtual void make_annotations(execution_context & ctx) {
@ -970,7 +979,7 @@ namespace datalog {
} }
return true; return true;
} }
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
out << "instr_assert_signature of " << m_tgt << " signature:"; out << "instr_assert_signature of " << m_tgt << " signature:";
print_container(m_sig, out); print_container(m_sig, out);
} }
@ -1042,7 +1051,7 @@ namespace datalog {
} }
} }
void instruction_block::display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const { void instruction_block::display_indented(rel_context const& ctx, std::ostream & out, std::string indentation) const {
instr_seq_type::const_iterator it = m_data.begin(); instr_seq_type::const_iterator it = m_data.begin();
instr_seq_type::const_iterator end = m_data.end(); instr_seq_type::const_iterator end = m_data.end();
for(; it!=end; ++it) { for(; it!=end; ++it) {

View file

@ -31,6 +31,7 @@ namespace datalog {
class execution_context; class execution_context;
class instruction_block; class instruction_block;
class rel_context;
inline void check_overflow(unsigned i) { inline void check_overflow(unsigned i) {
if (i == UINT_MAX) { if (i == UINT_MAX) {
@ -78,7 +79,7 @@ namespace datalog {
void reset(); void reset();
rel_context & get_rel_context() { return m_context.get_rel_context(); }; rel_context & get_rel_context();
void set_timelimit(unsigned time_in_ms); void set_timelimit(unsigned time_in_ms);
void reset_timelimit(); void reset_timelimit();
@ -91,10 +92,9 @@ namespace datalog {
If register contains zero, it should be treated as if it contains an empty relation. If register contains zero, it should be treated as if it contains an empty relation.
*/ */
reg_type reg(reg_idx i) { reg_type reg(reg_idx i) const {
if (i>=m_registers.size()) { if (i >= m_registers.size()) {
check_overflow(i); return 0;
m_registers.resize(i+1,0);
} }
return m_registers[i]; return m_registers[i];
} }
@ -102,27 +102,29 @@ namespace datalog {
\brief Return value of the register and assign zero into it place. \brief Return value of the register and assign zero into it place.
*/ */
reg_type release_reg(reg_idx i) { reg_type release_reg(reg_idx i) {
SASSERT(i<m_registers.size()); SASSERT(i < m_registers.size());
SASSERT(m_registers[i]); SASSERT(m_registers[i]);
reg_type res = m_registers[i]; reg_type res = m_registers[i];
m_registers[i] = 0; m_registers[i] = 0;
return res; return res;
} }
/** /**
\brief Assign value to a register. If it was non-empty, deallocate its content first. \brief Assign value to a register. If it was non-empty, deallocate its content first.
*/ */
void set_reg(reg_idx i, reg_type val) { void set_reg(reg_idx i, reg_type val) {
if(i>=m_registers.size()) { if (i >= m_registers.size()) {
check_overflow(i); check_overflow(i);
m_registers.resize(i+1,0); m_registers.resize(i+1,0);
} }
if(m_registers[i]) { if (m_registers[i]) {
m_registers[i]->deallocate(); m_registers[i]->deallocate();
} }
m_registers[i]=val; m_registers[i] = val;
} }
void make_empty(reg_idx i) { void make_empty(reg_idx i) {
if(reg(i)) { if (reg(i)) {
set_reg(i, 0); set_reg(i, 0);
} }
} }
@ -130,14 +132,16 @@ namespace datalog {
unsigned register_count() const { unsigned register_count() const {
return m_registers.size(); return m_registers.size();
} }
bool get_register_annotation(reg_idx reg, std::string & res) const { bool get_register_annotation(reg_idx reg, std::string & res) const {
return m_reg_annotation.find(reg, res); return m_reg_annotation.find(reg, res);
} }
void set_register_annotation(reg_idx reg, std::string str) { void set_register_annotation(reg_idx reg, std::string str) {
m_reg_annotation.insert(reg, str); m_reg_annotation.insert(reg, str);
} }
void report_big_relations(unsigned threshold, std::ostream & out); void report_big_relations(unsigned threshold, std::ostream & out) const;
}; };
@ -208,7 +212,7 @@ namespace datalog {
The newline character at the end should not be printed. The newline character at the end should not be printed.
*/ */
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const { virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
out << "<instruction>"; out << "<instruction>";
} }
/** /**
@ -216,7 +220,7 @@ namespace datalog {
Each line must be prepended by \c indentation and ended by a newline character. Each line must be prepended by \c indentation and ended by a newline character.
*/ */
virtual void display_body_impl(rel_context & ctx, std::ostream & out, std::string indentation) const {} virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const {}
public: public:
typedef execution_context::reg_type reg_type; typedef execution_context::reg_type reg_type;
typedef execution_context::reg_idx reg_idx; typedef execution_context::reg_idx reg_idx;
@ -227,10 +231,10 @@ namespace datalog {
virtual void make_annotations(execution_context & ctx) = 0; virtual void make_annotations(execution_context & ctx) = 0;
void display(rel_context & ctx, std::ostream & out) const { void display(rel_context const& ctx, std::ostream & out) const {
display_indented(ctx, out, ""); display_indented(ctx, out, "");
} }
void display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const; void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const;
static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt); static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt);
/** /**
@ -329,10 +333,10 @@ namespace datalog {
void make_annotations(execution_context & ctx); void make_annotations(execution_context & ctx);
void display(rel_context & ctx, std::ostream & out) const { void display(rel_context const & ctx, std::ostream & out) const {
display_indented(ctx, out, ""); display_indented(ctx, out, "");
} }
void display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const; void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const;
}; };

View file

@ -213,7 +213,7 @@ namespace datalog {
rule_set* rules = alloc(rule_set, m_ctx); rule_set* rules = alloc(rule_set, m_ctx);
rule_set::iterator it = source.begin(), end = source.end(); rule_set::iterator it = source.begin(), end = source.end();
bool change = false; bool change = false;
for (; it != end; ++it) { for (; !m_ctx.canceled() && it != end; ++it) {
change = blast(**it, *rules) || change; change = blast(**it, *rules) || change;
} }
if (!change) { if (!change) {

View file

@ -265,7 +265,7 @@ namespace datalog {
expr_ref fml(m); expr_ref fml(m);
reset(); reset();
rule_set * result = alloc(rule_set, m_context); rule_set * result = alloc(rule_set, m_context);
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; !m_context.canceled() && i < sz; ++i) {
rule * r = source.get_rule(i); rule * r = source.get_rule(i);
r->to_formula(fml); r->to_formula(fml);
if (blast(r, fml)) { if (blast(r, fml)) {

View file

@ -39,8 +39,8 @@ namespace datalog {
m(ctx.get_manager()), m(ctx.get_manager()),
m_rmanager(ctx), m_rmanager(ctx),
m_answer(m), m_answer(m),
m_cancel(false), m_last_result_relation(0),
m_last_result_relation(0) { m_ectx(ctx) {
// register plugins for builtin tables // register plugins for builtin tables
@ -94,9 +94,9 @@ namespace datalog {
decl_set original_predicates; decl_set original_predicates;
m_context.collect_predicates(original_predicates); m_context.collect_predicates(original_predicates);
instruction_block rules_code; m_code.reset();
instruction_block termination_code; instruction_block termination_code;
execution_context ex_ctx(m_context); m_ectx.reset();
lbool result; lbool result;
@ -104,9 +104,13 @@ namespace datalog {
while (true) { while (true) {
m_context.transform_rules(); m_context.transform_rules();
compiler::compile(m_context, m_context.get_rules(), rules_code, termination_code); if (m_context.canceled()) {
result = l_undef;
break;
}
compiler::compile(m_context, m_context.get_rules(), m_code, termination_code);
TRACE("dl", rules_code.display(*this, tout); ); TRACE("dl", m_code.display(*this, tout); );
bool timeout_after_this_round = time_limit && (restart_time==0 || remaining_time_limit<=restart_time); bool timeout_after_this_round = time_limit && (restart_time==0 || remaining_time_limit<=restart_time);
@ -114,29 +118,32 @@ namespace datalog {
unsigned timeout = time_limit ? (restart_time!=0) ? unsigned timeout = time_limit ? (restart_time!=0) ?
std::min(remaining_time_limit, restart_time) std::min(remaining_time_limit, restart_time)
: remaining_time_limit : restart_time; : remaining_time_limit : restart_time;
ex_ctx.set_timelimit(timeout); m_ectx.set_timelimit(timeout);
} }
bool early_termination = !rules_code.perform(ex_ctx); bool early_termination = !m_code.perform(m_ectx);
ex_ctx.reset_timelimit(); m_ectx.reset_timelimit();
VERIFY( termination_code.perform(ex_ctx) ); VERIFY( termination_code.perform(m_ectx) || m_context.canceled());
rules_code.process_all_costs(); m_code.process_all_costs();
IF_VERBOSE(10, ex_ctx.report_big_relations(1000, verbose_stream());); IF_VERBOSE(10, m_ectx.report_big_relations(1000, verbose_stream()););
if (m_context.canceled()) {
result = l_undef;
break;
}
if (!early_termination) { if (!early_termination) {
m_context.set_status(OK); m_context.set_status(OK);
result = l_true; result = l_true;
break; break;
} }
if (memory::above_high_watermark()) { if (memory::above_high_watermark()) {
m_context.set_status(MEMOUT); m_context.set_status(MEMOUT);
result = l_undef; result = l_undef;
break; break;
} }
if (timeout_after_this_round || m_cancel) { if (timeout_after_this_round) {
m_context.set_status(TIMEOUT); m_context.set_status(TIMEOUT);
result = l_undef; result = l_undef;
break; break;
@ -154,9 +161,7 @@ namespace datalog {
restart_time = static_cast<unsigned>(new_restart_time); restart_time = static_cast<unsigned>(new_restart_time);
} }
rules_code.reset(); termination_code.reset();
termination_code.reset();
ex_ctx.reset();
m_context.reopen(); m_context.reopen();
restrict_predicates(original_predicates); restrict_predicates(original_predicates);
m_context.replace_rules(original_rules); m_context.replace_rules(original_rules);
@ -164,10 +169,12 @@ namespace datalog {
} }
m_context.reopen(); m_context.reopen();
restrict_predicates(original_predicates); restrict_predicates(original_predicates);
m_context.record_transformed_rules();
m_context.replace_rules(original_rules); m_context.replace_rules(original_rules);
m_context.close(); m_context.close();
TRACE("dl", ex_ctx.report_big_relations(100, tout);); TRACE("dl", m_ectx.report_big_relations(100, tout););
m_cancel = false; m_code.process_all_costs();
m_code.make_annotations(m_ectx);
return result; return result;
} }
@ -504,5 +511,17 @@ namespace datalog {
get_rmanager().display(out); get_rmanager().display(out);
} }
void rel_context::display_profile(std::ostream& out) const {
out << "\n--------------\n";
out << "Instructions\n";
m_code.display(*this, out);
out << "\n--------------\n";
out << "Big relations\n";
m_ectx.report_big_relations(1000, out);
get_rmanager().display_relation_sizes(out);
}
}; };

View file

@ -22,6 +22,7 @@ Revision History:
#define _REL_CONTEXT_H_ #define _REL_CONTEXT_H_
#include "ast.h" #include "ast.h"
#include "dl_relation_manager.h" #include "dl_relation_manager.h"
#include "dl_instruction.h"
#include "lbool.h" #include "lbool.h"
namespace datalog { namespace datalog {
@ -35,10 +36,11 @@ namespace datalog {
ast_manager& m; ast_manager& m;
relation_manager m_rmanager; relation_manager m_rmanager;
expr_ref m_answer; expr_ref m_answer;
volatile bool m_cancel;
relation_base * m_last_result_relation; relation_base * m_last_result_relation;
decl_set m_output_preds; decl_set m_output_preds;
fact_vector m_table_facts; fact_vector m_table_facts;
execution_context m_ectx;
instruction_block m_code;
void reset_negated_tables(); void reset_negated_tables();
@ -53,8 +55,8 @@ namespace datalog {
relation_manager & get_rmanager(); relation_manager & get_rmanager();
const relation_manager & get_rmanager() const; const relation_manager & get_rmanager() const;
ast_manager& get_manager() { return m; } ast_manager& get_manager() const { return m; }
context& get_context() { return m_context; } context& get_context() const { return m_context; }
relation_base & get_relation(func_decl * pred); relation_base & get_relation(func_decl * pred);
relation_base * try_get_relation(func_decl * pred) const; relation_base * try_get_relation(func_decl * pred) const;
expr_ref get_last_answer() { return m_answer; } expr_ref get_last_answer() { return m_answer; }
@ -70,10 +72,6 @@ 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 cancel() { m_cancel = true; }
void cleanup() { m_cancel = false; }
/** /**
\brief Restrict the set of used predicates to \c res. \brief Restrict the set of used predicates to \c res.
@ -107,6 +105,8 @@ namespace datalog {
void display_output_facts(std::ostream & out) const; void display_output_facts(std::ostream & out) const;
void display_facts(std::ostream & out) const; void display_facts(std::ostream & out) const;
void display_profile(std::ostream& out) const;
lbool saturate(); lbool saturate();
}; };

View file

@ -209,7 +209,6 @@ unsigned read_datalog(char const * file) {
rules_code.make_annotations(ex_ctx); rules_code.make_annotations(ex_ctx);
ex_ctx.set_timelimit(timeout); ex_ctx.set_timelimit(timeout);
SASSERT(!ex_ctx.should_terminate());
early_termination = !rules_code.perform(ex_ctx); early_termination = !rules_code.perform(ex_ctx);
if(early_termination) { if(early_termination) {