z3-z3-4.13.0.src.tactic.probe.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
probe.cpp
Abstract:
Evaluates/Probes a goal.
A probe is used to build tactics (aka strategies) that
makes decisions based on the structure of a goal.
Author:
Leonardo de Moura (leonardo) 2011-10-13.
Revision History:
--*/
#include "tactic/probe.h"
#include "ast/arith_decl_plugin.h"
#include "ast/bv_decl_plugin.h"
#include "tactic/goal_util.h"
#include "ast/rewriter/bv_rewriter.h"
class memory_probe : public probe {
public:
result operator()(goal const & g) override {
return result(static_cast(memory::get_allocation_size())/static_cast(1024*1024));
}
};
probe * mk_memory_probe() {
return alloc(memory_probe);
}
class depth_probe : public probe {
public:
result operator()(goal const & g) override {
return result(g.depth());
}
};
class size_probe : public probe {
public:
result operator()(goal const & g) override {
return result(g.size());
}
};
class num_exprs_probe : public probe {
public:
result operator()(goal const & g) override {
return result(g.num_exprs());
}
};
probe * mk_depth_probe() {
return alloc(depth_probe);
}
probe * mk_size_probe() {
return alloc(size_probe);
}
probe * mk_num_exprs_probe() {
return alloc(num_exprs_probe);
}
class unary_probe : public probe {
protected:
probe * m_p;
public:
unary_probe(probe * p):
m_p(p) {
SASSERT(p);
p->inc_ref();
}
~unary_probe() override {
m_p->dec_ref();
}
};
class bin_probe : public probe {
protected:
probe * m_p1;
probe * m_p2;
public:
bin_probe(probe * p1, probe * p2):
m_p1(p1),
m_p2(p2) {
SASSERT(p1);
SASSERT(p2);
p1->inc_ref();
p2->inc_ref();
}
~bin_probe() override {
m_p1->dec_ref();
m_p2->dec_ref();
}
};
class not_probe : public unary_probe {
public:
not_probe(probe * p):unary_probe(p) {}
result operator()(goal const & g) override {
return result(!m_p->operator()(g).is_true());
}
};
class and_probe : public bin_probe {
public:
and_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).is_true() && m_p2->operator()(g).is_true());
}
};
class or_probe : public bin_probe {
public:
or_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).is_true() || m_p2->operator()(g).is_true());
}
};
class eq_probe : public bin_probe {
public:
eq_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() == m_p2->operator()(g).get_value());
}
};
class le_probe : public bin_probe {
public:
le_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() <= m_p2->operator()(g).get_value());
}
};
class add_probe : public bin_probe {
public:
add_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() + m_p2->operator()(g).get_value());
}
};
class sub_probe : public bin_probe {
public:
sub_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() - m_p2->operator()(g).get_value());
}
};
class mul_probe : public bin_probe {
public:
mul_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() * m_p2->operator()(g).get_value());
}
};
class div_probe : public bin_probe {
public:
div_probe(probe * p1, probe * p2):bin_probe(p1, p2) {}
result operator()(goal const & g) override {
return result(m_p1->operator()(g).get_value() / m_p2->operator()(g).get_value());
}
};
class const_probe : public probe {
double m_val;
public:
const_probe(double v):m_val(v) {}
result operator()(goal const & g) override {
return result(m_val);
}
};
probe * mk_const_probe(double v) {
return alloc(const_probe, v);
}
probe * mk_not(probe * p) {
return alloc(not_probe, p);
}
probe * mk_and(probe * p1, probe * p2) {
return alloc(and_probe, p1, p2);
}
probe * mk_or(probe * p1, probe * p2) {
return alloc(or_probe, p1, p2);
}
probe * mk_implies(probe * p1, probe * p2) {
return mk_or(mk_not(p1), p2);
}
probe * mk_eq(probe * p1, probe * p2) {
return alloc(eq_probe, p1, p2);
}
probe * mk_neq(probe * p1, probe * p2) {
return mk_not(mk_eq(p1, p2));
}
probe * mk_le(probe * p1, probe * p2) {
return alloc(le_probe, p1, p2);
}
probe * mk_ge(probe * p1, probe * p2) {
return mk_le(p2, p1);
}
probe * mk_lt(probe * p1, probe * p2) {
return mk_not(mk_ge(p1, p2));
}
probe * mk_gt(probe * p1, probe * p2) {
return mk_lt(p2, p1);
}
probe * mk_add(probe * p1, probe * p2) {
return alloc(add_probe, p1, p2);
}
probe * mk_mul(probe * p1, probe * p2) {
return alloc(mul_probe, p1, p2);
}
probe * mk_sub(probe * p1, probe * p2) {
return alloc(sub_probe, p1, p2);
}
probe * mk_div(probe * p1, probe * p2) {
return alloc(div_probe, p1, p2);
}
struct is_non_propositional_predicate {
struct found {};
ast_manager & m;
is_non_propositional_predicate(ast_manager & _m):m(_m) {}
void operator()(var *) { throw found(); }
void operator()(quantifier *) { throw found(); }
void operator()(app * n) {
if (!m.is_bool(n))
throw found();
family_id fid = n->get_family_id();
if (fid == m.get_basic_family_id())
return;
if (is_uninterp_const(n))
return;
throw found();
}
};
struct is_non_qfbv_predicate {
struct found {};
ast_manager & m;
bv_util u;
is_non_qfbv_predicate(ast_manager & _m):m(_m), u(m) {}
void operator()(var *) { throw found(); }
void operator()(quantifier *) { throw found(); }
void operator()(app * n) {
if (!m.is_bool(n) && !u.is_bv(n))
throw found();
family_id fid = n->get_family_id();
if (fid == m.get_basic_family_id())
return;
if (fid == u.get_family_id()) {
if (n->get_decl_kind() == OP_BSDIV0 ||
n->get_decl_kind() == OP_BUDIV0 ||
n->get_decl_kind() == OP_BSREM0 ||
n->get_decl_kind() == OP_BUREM0 ||
n->get_decl_kind() == OP_BSMOD0)
throw found();
return;
}
if (is_uninterp_const(n))
return;
throw found();
}
};
class is_propositional_probe : public probe {
public:
result operator()(goal const & g) override {
return !test(g);
}
};
class is_qfbv_probe : public probe {
public:
result operator()(goal const & g) override {
return !test(g);
}
};
probe * mk_is_propositional_probe() {
return alloc(is_propositional_probe);
}
probe * mk_is_qfbv_probe() {
return alloc(is_qfbv_probe);
}
struct is_non_qfaufbv_predicate {
struct found {};
ast_manager & m;
bv_util m_bv_util;
array_util m_array_util;
is_non_qfaufbv_predicate(ast_manager & _m) : m(_m), m_bv_util(_m), m_array_util(_m) {}
void operator()(var *) { throw found(); }
void operator()(quantifier *) { throw found(); }
void operator()(app * n) {
if (!m.is_bool(n) && !m_bv_util.is_bv(n) && !m_array_util.is_array(n))
throw found();
family_id fid = n->get_family_id();
if (fid == m.get_basic_family_id())
return;
if (fid == m_bv_util.get_family_id() || fid == m_array_util.get_family_id())
return;
if (is_uninterp(n))
return;
throw found();
}
};
class is_qfaufbv_probe : public probe {
public:
result operator()(goal const & g) override {
return !test(g);
}
};
probe * mk_is_qfaufbv_probe() {
return alloc(is_qfaufbv_probe);
}
struct is_non_qfufbv_predicate {
struct found {};
ast_manager & m;
bv_util m_bv_util;
is_non_qfufbv_predicate(ast_manager & _m) : m(_m), m_bv_util(_m) {}
void operator()(var *) { throw found(); }
void operator()(quantifier *) { throw found(); }
void operator()(app * n) {
if (!m.is_bool(n) && !m_bv_util.is_bv(n))
throw found();
family_id fid = n->get_family_id();
if (fid == m.get_basic_family_id())
return;
if (fid == m_bv_util.get_family_id())
return;
if (is_uninterp(n))
return;
throw found();
}
};
class is_qfufbv_probe : public probe {
public:
result operator()(goal const & g) override {
return !test(g);
}
};
probe * mk_is_qfufbv_probe() {
return alloc(is_qfufbv_probe);
}
class num_consts_probe : public probe {
bool m_bool; // If true, track only boolean constants. Otherwise, track only non boolean constants.
char const * m_family; // (Ignored if m_bool == true), if != 0 and m_bool == true, then track only constants of the given family.
struct proc {
ast_manager & m;
bool m_bool;
family_id m_fid;
unsigned m_counter;
proc(ast_manager & _m, bool b, char const * family):m(_m), m_bool(b), m_counter(0) {
if (family != nullptr)
m_fid = m.mk_family_id(family);
else
m_fid = null_family_id;
}
void operator()(quantifier *) {}
void operator()(var *) {}
void operator()(app * n) {
if (n->get_num_args() == 0 && !m.is_value(n)) {
if (m_bool) {
if (m.is_bool(n))
m_counter++;
}
else {
if (m_fid == null_family_id) {
if (!m.is_bool(n))
m_counter++;
}
else {
if (n->get_sort()->get_family_id() == m_fid)
m_counter++;
}
}
}
}
};
public:
num_consts_probe(bool b, char const * f):
m_bool(b), m_family(f) {
}
result operator()(goal const & g) override {
proc p(g.m(), m_bool, m_family);
unsigned sz = g.size();
expr_fast_mark1 visited;
for (unsigned i = 0; i < sz; i++) {
for_each_expr_core(p, visited, g.form(i));
}
return result(p.m_counter);
}
};
probe * mk_num_consts_probe() {
return alloc(num_consts_probe, false, nullptr);
}
probe * mk_num_bool_consts_probe() {
return alloc(num_consts_probe, true, nullptr);
}
probe * mk_num_arith_consts_probe() {
return alloc(num_consts_probe, false, "arith");
}
probe * mk_num_bv_consts_probe() {
return alloc(num_consts_probe, false, "bv");
}
class produce_proofs_probe : public probe {
public:
result operator()(goal const & g) override {
return g.proofs_enabled();
}
};
class produce_models_probe : public probe {
public:
result operator()(goal const & g) override {
return g.models_enabled();
}
};
class produce_unsat_cores_probe : public probe {
public:
result operator()(goal const & g) override {
return g.unsat_core_enabled();
}
};
probe * mk_produce_proofs_probe() {
return alloc(produce_proofs_probe);
}
probe * mk_produce_models_probe() {
return alloc(produce_models_probe);
}
probe * mk_produce_unsat_cores_probe() {
return alloc(produce_unsat_cores_probe);
}
struct has_pattern_probe : public probe {
struct found {};
struct proc {
void operator()(var * n) {}
void operator()(app * n) {}
void operator()(quantifier * n) {
if (n->get_num_patterns() > 0 || n->get_num_no_patterns() > 0)
throw found();
}
};
public:
result operator()(goal const & g) override {
try {
expr_fast_mark1 visited;
proc p;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
quick_for_each_expr(p, visited, g.form(i));
}
return false;
}
catch (const found &) {
return true;
}
}
};
probe * mk_has_pattern_probe() {
return alloc(has_pattern_probe);
}
struct has_quantifier_probe : public probe {
struct found {};
struct proc {
void operator()(var * n) {}
void operator()(app * n) {}
void operator()(quantifier * n) { throw found(); }
};
public:
result operator()(goal const & g) override {
try {
expr_fast_mark1 visited;
proc p;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
quick_for_each_expr(p, visited, g.form(i));
}
return false;
}
catch (const found &) {
return true;
}
}
};
probe * mk_has_quantifier_probe() {
return alloc(has_quantifier_probe);
}