3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 20:38:43 +00:00

update scoring function for tab context

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-01-28 10:37:31 -08:00
parent c482ede7ff
commit 0eea0bea9a
2 changed files with 216 additions and 57 deletions

View file

@ -54,8 +54,9 @@ def_module_params('fixedpoint',
"if true, finite_product_relation will attempt to avoid creating inner relation with empty signature "
"by putting in half of the table columns, if it would have been empty otherwise"),
('print_answer', BOOL, False, 'print answer instance(s) to query'),
('print_certificate', BOOL, False, 'print certificate for reacahbility or non-reachability'),
('print_certificate', BOOL, False, 'print certificate for reachability or non-reachability'),
('print_statistics', BOOL, False, 'print statistics'),
('tab_selection', SYMBOL, 'weight', 'selection method for tabular strategy: weight (default), first, var-use'),
))

View file

@ -28,6 +28,7 @@ Revision History:
#include "th_rewriter.h"
#include "datatype_decl_plugin.h"
#include "for_each_expr.h"
#include "matcher.h"
namespace tb {
@ -420,17 +421,17 @@ namespace tb {
class rules {
typedef obj_map<func_decl, unsigned_vector> map;
vector<ref<clause> > m_rules;
map m_index;
map m_index;
public:
typedef vector<ref<clause> >::const_iterator iterator;
iterator begin() const { return m_rules.begin(); }
iterator end() const { return m_rules.end(); }
void init(datalog::rule_set const& rules) {
m_rules.reset();
m_index.reset();
reset();
datalog::rule_manager& rm = rules.get_rule_manager();
datalog::rule_ref r(rm);
datalog::rule_set::iterator it = rules.begin();
@ -453,7 +454,7 @@ namespace tb {
e->get_data().m_value.push_back(idx);
}
unsigned get_num_rules(func_decl* p) {
unsigned get_num_rules(func_decl* p) const {
map::obj_map_entry* e = m_index.find_core(p);
if (p) {
return e->get_data().get_value().size();
@ -463,12 +464,25 @@ namespace tb {
}
}
void get_decls(ptr_vector<func_decl>& decls) const {
map::iterator it = m_index.begin();
map::iterator end = m_index.end();
for (; it != end; ++it) {
decls.push_back(it->m_key);
}
}
ref<clause> get_rule(func_decl* p, unsigned idx) const {
map::obj_map_entry* e = m_index.find_core(p);
SASSERT(p);
unsigned rule_id = e->get_data().get_value()[idx];
return m_rules[rule_id];
}
private:
void reset() {
m_rules.reset();
m_index.reset();
}
};
@ -720,102 +734,240 @@ namespace tb {
// predicate selection strategy.
class selection {
enum strategy {
WEIGHT_SELECT,
FIRST_SELECT,
VAR_USE_SELECT
};
typedef svector<double> double_vector;
typedef obj_map<func_decl, double_vector> score_map;
datalog::context& m_ctx;
ast_manager& m;
datatype_util dt;
obj_map<func_decl, unsigned_vector> m_scores;
unsigned_vector m_score_values;
score_map m_score_map;
double_vector m_scores;
double_vector m_var_scores;
strategy m_strategy;
public:
selection(datalog::context& ctx):
m_ctx(ctx),
m(ctx.get_manager()),
dt(m) {
set_strategy(ctx.get_params().tab_selection());
}
void init(rules const& rs) {
m_scores.reset();
reset();
double_vector& scores = m_scores;
rules::iterator it = rs.begin(), end = rs.end();
for (; it != end; ++it) {
ref<clause> g = *it;
app* p = g->get_head();
unsigned_vector scores;
scores.reset();
score_predicate(p, scores);
insert_score(p->get_decl(), scores);
}
normalize_scores(rs);
}
unsigned select(clause const& g) {
switch(m_strategy) {
case WEIGHT_SELECT:
return weight_select(g);
case FIRST_SELECT:
return trivial_select(g);
case VAR_USE_SELECT:
return andrei_select(g);
default:
return weight_select(g);
}
}
void reset() {
m_score_map.reset();
m_scores.reset();
m_var_scores.reset();
}
private:
// determine if constructors in p are matches by rules.
bool is_reductive(app* p, double_vector const& p_scores) {
func_decl* f = p->get_decl();
score_map::obj_map_entry* e = m_score_map.find_core(p->get_decl());
if (!e) {
return false;
}
double_vector const& scores = e->get_data().m_value;
SASSERT(scores.size() == p->get_num_args());
bool has_reductive = false;
bool is_red = true;
for (unsigned i = 0; is_red && i < scores.size(); ++i) {
if (scores[i] >= 1) {
has_reductive = true;
is_red &= p_scores[i] >= 1;
}
}
return has_reductive && is_red;
}
void set_strategy(symbol const& str) {
if (str == symbol("weight")) {
m_strategy = WEIGHT_SELECT;
}
else if (str == symbol("first")) {
m_strategy = FIRST_SELECT;
}
else if (str == symbol("var-use")) {
m_strategy = VAR_USE_SELECT;
}
else {
m_strategy = WEIGHT_SELECT;
}
}
unsigned trivial_select(clause const& g) {
return 0;
#if 0
unsigned max_score = 0;
}
unsigned andrei_select(clause const& g) {
score_variables(g);
double_vector& scores = m_scores;
double max_score = 0;
unsigned result = 0;
unsigned_vector& scores = m_score_values;
for (unsigned i = 0; i < g.get_num_predicates(); ++i) {
scores.reset();
double_vector p_scores;
double score = 0;
app* p = g.get_predicate(i);
score_predicate(p, scores);
unsigned score = compute_score(p->get_decl(), scores);
m_score_map.find(p->get_decl(), p_scores);
SASSERT(p_scores.empty() || p->get_num_args() == p_scores.size());
p_scores.resize(p->get_num_args());
for (unsigned j = 0; j < p->get_num_args(); ++j) {
if (is_var(p->get_arg(j))) {
unsigned idx = to_var(p->get_arg(j))->get_idx();
score += m_var_scores[idx];
}
else {
IF_VERBOSE(1, verbose_stream() << p_scores[j] << " " << scores[j] << "\n";);
score += p_scores[j]*scores[j];
}
}
IF_VERBOSE(1, verbose_stream() << "score: " << mk_pp(p, m) << " " << score << "\n";);
if (score > max_score) {
max_score = score;
result = i;
}
}
return result;
#endif
IF_VERBOSE(1, verbose_stream() << "select:" << result << "\n";);
return result;
}
void reset() {
m_scores.reset();
m_score_values.reset();
}
private:
unsigned compute_score(func_decl* f, unsigned_vector const& scores) {
unsigned_vector f_scores;
unsigned score = 0;
if (m_scores.find(f, f_scores)) {
SASSERT(f_scores.size() == scores.size());
for (unsigned i = 0; i < scores.size(); ++i) {
score += scores[i]*f_scores[i];
unsigned weight_select(clause const& g) {
double_vector& scores = m_scores;
double max_score = 0;
unsigned result = 0;
for (unsigned i = 0; i < g.get_num_predicates(); ++i) {
scores.reset();
double score = 0;
app* p = g.get_predicate(i);
score_predicate(p, scores);
for (unsigned j = 0; j < scores.size(); ++j) {
score += scores[j];
}
IF_VERBOSE(1, verbose_stream() << "score: " << mk_pp(p, m) << " " << score << "\n";);
if (score > max_score) {
max_score = score;
result = i;
}
}
// else there is no rule.
return score;
IF_VERBOSE(1, verbose_stream() << "select " << result << "\n";);
return result;
}
void score_variables(clause const& g) {
m_var_scores.reset();
for (unsigned i = 0; i < g.get_num_predicates(); ++i) {
app* p = g.get_predicate(i);
score_variables(p);
}
}
void score_variables(app* p) {
score_map::obj_map_entry* e = m_score_map.find_core(p->get_decl());
if (!e) {
return;
}
double_vector& scores = e->get_data().m_value;
for (unsigned i = 0; i < p->get_num_args(); ++i) {
if (is_var(p->get_arg(i))) {
unsigned idx = to_var(p->get_arg(i))->get_idx();
if (m_var_scores.size() <= idx) {
m_var_scores.resize(idx+1);
}
m_var_scores[idx] += scores[i];
}
}
}
void normalize_scores(rules const& rs) {
ptr_vector<func_decl> decls;
rs.get_decls(decls);
for (unsigned i = 0; i < decls.size(); ++i) {
unsigned nr = rs.get_num_rules(decls[i]);
score_map::obj_map_entry& e = *m_score_map.find_core(decls[i]);
double_vector& scores = e.get_data().m_value;
for (unsigned j = 0; j < scores.size(); ++j) {
scores[j] = scores[j]/nr;
}
}
}
void score_predicate(app* p, unsigned_vector& scores) {
void score_predicate(app* p, double_vector& scores) {
for (unsigned i = 0; i < p->get_num_args(); ++i) {
scores.push_back(score_argument(p->get_arg(i)));
}
}
unsigned score_argument(expr* arg) {
if (is_var(arg)) {
return 0;
}
if (m.is_value(arg)) {
return 3;
}
if (is_app(arg) && dt.is_constructor(to_app(arg)->get_decl())) {
return 2;
}
return 1;
unsigned score = 0;
score_argument(arg, score, 20);
return score;
}
void insert_score(func_decl* f, unsigned_vector const& scores) {
obj_map<func_decl, unsigned_vector>::obj_map_entry* e;
e = m_scores.find_core(f);
void score_argument(expr* arg, unsigned& score, unsigned max_score) {
if (score < max_score && is_app(arg)) {
app* a = to_app(arg);
if (dt.is_constructor(a->get_decl())) {
score += 1;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
score_argument(a->get_arg(i), score, max_score);
}
}
else if (m.is_value(a)) {
++score;
}
}
}
void insert_score(func_decl* f, double_vector const& scores) {
score_map::obj_map_entry* e = m_score_map.find_core(f);
if (e) {
unsigned_vector & old_scores = e->get_data().m_value;
double_vector & old_scores = e->get_data().m_value;
SASSERT(scores.size() == old_scores.size());
for (unsigned i = 0; i < scores.size(); ++i) {
old_scores[i] += scores[i];
}
}
else {
m_scores.insert(f, scores);
m_score_map.insert(f, scores);
}
}
};
@ -1255,7 +1407,8 @@ namespace datalog {
void display_premise(tb::clause& p, std::ostream& out) {
func_decl* f = p.get_predicate(p.get_predicate_index())->get_decl();
out << "{g" << p.get_seqno() << " " << f->get_name() << " pos: " << p.get_predicate_index() << " rule: " << p.get_next_rule() << "}\n";
out << "{g" << p.get_seqno() << " " << f->get_name() << " pos: "
<< p.get_predicate_index() << " rule: " << p.get_next_rule() << "}\n";
}
void display_clause(tb::clause& g, std::ostream& out) {
@ -1266,7 +1419,6 @@ namespace datalog {
scoped_proof sp(m);
proof_ref pr(m);
proof_ref_vector prs(m);
expr_ref_vector subst(m);
ref<tb::clause> clause = get_clause();
ref<tb::clause> replayed_clause;
replace_proof_converter pc(m);
@ -1293,20 +1445,26 @@ namespace datalog {
clause = parent;
substs.push_back(s1);
}
for (unsigned i = substs.size(); i > 0; ) {
--i;
apply_subst(subst, substs[i]);
}
expr_ref body = clause->get_body();
var_subst vs(m, false);
vs(body, subst.size(), subst.c_ptr(), body);
IF_VERBOSE(1, verbose_stream() << mk_pp(body, m) << "\n";);
IF_VERBOSE(1, display_body_insts(substs, *clause, verbose_stream()););
pc.invert();
prs.push_back(m.mk_asserted(root));
pc(m, 1, prs.c_ptr(), pr);
return pr;
}
void display_body_insts(vector<expr_ref_vector> const& substs, tb::clause const& clause, std::ostream& out) const {
expr_ref_vector subst(m);
for (unsigned i = substs.size(); i > 0; ) {
--i;
apply_subst(subst, substs[i]);
}
expr_ref body = clause.get_body();
var_subst vs(m, false);
vs(body, subst.size(), subst.c_ptr(), body);
out << mk_pp(body, m) << "\n";
}
void resolve_rule(replace_proof_converter& pc, tb::clause const& r1, tb::clause const& r2,
expr_ref_vector const& s1, expr_ref_vector const& s2, tb::clause const& res) const {
unsigned idx = r1.get_predicate_index();