mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
merge with unstable
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
88df909a6c
32 changed files with 578 additions and 1947 deletions
|
@ -28,7 +28,6 @@ enum arith_solver_id {
|
|||
AS_ARITH,
|
||||
AS_DENSE_DIFF_LOGIC,
|
||||
AS_UTVPI,
|
||||
AS_HORN,
|
||||
AS_OPTINF
|
||||
};
|
||||
|
||||
|
|
|
@ -441,10 +441,10 @@ namespace smt {
|
|||
virtual bool mbqi_enabled(quantifier *q) const {
|
||||
if(!m_fparams->m_mbqi_id) return true;
|
||||
const symbol &s = q->get_qid();
|
||||
unsigned len = strlen(m_fparams->m_mbqi_id);
|
||||
size_t len = strlen(m_fparams->m_mbqi_id);
|
||||
if(s == symbol::null || s.is_numerical())
|
||||
return len == 0;
|
||||
return strncmp(s.bare_str(),m_fparams->m_mbqi_id,static_cast<unsigned>(len)) == 0;
|
||||
return strncmp(s.bare_str(),m_fparams->m_mbqi_id,len) == 0;
|
||||
}
|
||||
|
||||
/* Quantifier id's must begin with the prefix specified by
|
||||
|
|
|
@ -22,7 +22,6 @@ Revision History:
|
|||
#include"theory_arith.h"
|
||||
#include"theory_dense_diff_logic.h"
|
||||
#include"theory_diff_logic.h"
|
||||
#include"theory_horn_ineq.h"
|
||||
#include"theory_utvpi.h"
|
||||
#include"theory_array.h"
|
||||
#include"theory_array_full.h"
|
||||
|
@ -731,12 +730,6 @@ namespace smt {
|
|||
m_context.register_plugin(alloc(smt::theory_dense_mi, m_manager, m_params));
|
||||
}
|
||||
break;
|
||||
case AS_HORN:
|
||||
if (m_params.m_arith_int_only)
|
||||
m_context.register_plugin(alloc(smt::theory_ihi, m_manager));
|
||||
else
|
||||
m_context.register_plugin(alloc(smt::theory_rhi, m_manager));
|
||||
break;
|
||||
case AS_UTVPI:
|
||||
if (m_params.m_arith_int_only)
|
||||
m_context.register_plugin(alloc(smt::theory_iutvpi, m_manager));
|
||||
|
|
|
@ -139,22 +139,32 @@ protected:
|
|||
SASSERT(g.is_well_sorted());
|
||||
}
|
||||
|
||||
struct expr_pos {
|
||||
unsigned m_parent;
|
||||
unsigned m_self;
|
||||
unsigned m_idx;
|
||||
expr* m_expr;
|
||||
expr_pos(unsigned p, unsigned s, unsigned i, expr* e):
|
||||
m_parent(p), m_self(s), m_idx(i), m_expr(e)
|
||||
{}
|
||||
expr_pos():
|
||||
m_parent(0), m_self(0), m_idx(0), m_expr(0)
|
||||
{}
|
||||
};
|
||||
|
||||
void reduce(expr_ref& result){
|
||||
SASSERT(m.is_bool(result));
|
||||
ptr_vector<expr> todo;
|
||||
ptr_vector<expr> names;
|
||||
svector<bool> is_checked;
|
||||
svector<unsigned> parent_ids, self_ids;
|
||||
svector<expr_pos> todo;
|
||||
expr_ref_vector fresh_vars(m), trail(m);
|
||||
expr_ref res(m), tmp(m);
|
||||
obj_map<expr,std::pair<unsigned, expr*> > cache;
|
||||
unsigned id = 1;
|
||||
obj_map<expr, expr_pos> cache;
|
||||
unsigned id = 1, child_id = 0;
|
||||
expr_ref n2(m), fml(m);
|
||||
unsigned path_id = 0, self_pos = 0;
|
||||
unsigned parent_pos = 0, self_pos = 0, self_idx = 0;
|
||||
app * a;
|
||||
unsigned sz;
|
||||
std::pair<unsigned,expr*> path_r;
|
||||
ptr_vector<expr> found;
|
||||
expr_pos path_r;
|
||||
expr_ref_vector args(m);
|
||||
expr_ref n = mk_fresh(id, m.mk_bool_sort());
|
||||
trail.push_back(n);
|
||||
|
@ -163,26 +173,25 @@ protected:
|
|||
tmp = m.mk_not(m.mk_iff(fml, n));
|
||||
m_solver.assert_expr(tmp);
|
||||
|
||||
todo.push_back(fml);
|
||||
todo.push_back(expr_pos(0,0,0,fml));
|
||||
names.push_back(n);
|
||||
is_checked.push_back(false);
|
||||
parent_ids.push_back(0);
|
||||
self_ids.push_back(0);
|
||||
m_solver.push();
|
||||
|
||||
while (!todo.empty() && !m_cancel) {
|
||||
expr_ref res(m);
|
||||
args.reset();
|
||||
expr* e = todo.back();
|
||||
unsigned pos = parent_ids.back();
|
||||
expr* e = todo.back().m_expr;
|
||||
self_pos = todo.back().m_self;
|
||||
parent_pos = todo.back().m_parent;
|
||||
self_idx = todo.back().m_idx;
|
||||
n = names.back();
|
||||
bool checked = is_checked.back();
|
||||
|
||||
if (cache.contains(e)) {
|
||||
goto done;
|
||||
}
|
||||
if (m.is_bool(e) && !checked && simplify_bool(n, res)) {
|
||||
TRACE("ctx_solver_simplify_tactic", tout << "simplified: " << mk_pp(e, m) << " |-> " << mk_pp(res, m) << "\n";);
|
||||
if (m.is_bool(e) && simplify_bool(n, res)) {
|
||||
TRACE("ctx_solver_simplify_tactic",
|
||||
tout << "simplified: " << mk_pp(e, m) << " |-> " << mk_pp(res, m) << "\n";);
|
||||
goto done;
|
||||
}
|
||||
if (!is_app(e)) {
|
||||
|
@ -191,49 +200,31 @@ protected:
|
|||
}
|
||||
|
||||
a = to_app(e);
|
||||
if (!is_checked.back()) {
|
||||
self_ids.back() = ++path_id;
|
||||
is_checked.back() = true;
|
||||
}
|
||||
self_pos = self_ids.back();
|
||||
sz = a->get_num_args();
|
||||
|
||||
sz = a->get_num_args();
|
||||
n2 = 0;
|
||||
|
||||
found.reset(); // arguments already simplified.
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
expr* arg = a->get_arg(i);
|
||||
if (cache.find(arg, path_r) && !found.contains(arg)) {
|
||||
if (cache.find(arg, path_r)) {
|
||||
//
|
||||
// This is a single traversal version of the context
|
||||
// simplifier. It simplifies only the first occurrence of
|
||||
// a sub-term with respect to the context.
|
||||
//
|
||||
|
||||
found.push_back(arg);
|
||||
if (path_r.first == self_pos) {
|
||||
TRACE("ctx_solver_simplify_tactic", tout << "cached " << mk_pp(arg, m) << " |-> " << mk_pp(path_r.second, m) << "\n";);
|
||||
args.push_back(path_r.second);
|
||||
}
|
||||
else if (m.is_bool(arg)) {
|
||||
res = local_simplify(a, n, id, i);
|
||||
TRACE("ctx_solver_simplify_tactic",
|
||||
tout << "Already cached: " << path_r.first << " " << mk_pp(arg, m) << " |-> " << mk_pp(res, m) << "\n";);
|
||||
args.push_back(res);
|
||||
if (path_r.m_parent == self_pos && path_r.m_idx == i) {
|
||||
args.push_back(path_r.m_expr);
|
||||
}
|
||||
else {
|
||||
args.push_back(arg);
|
||||
}
|
||||
}
|
||||
else if (!n2 && !found.contains(arg)) {
|
||||
else if (!n2) {
|
||||
n2 = mk_fresh(id, m.get_sort(arg));
|
||||
trail.push_back(n2);
|
||||
todo.push_back(arg);
|
||||
parent_ids.push_back(self_pos);
|
||||
self_ids.push_back(0);
|
||||
todo.push_back(expr_pos(self_pos, child_id++, i, arg));
|
||||
names.push_back(n2);
|
||||
args.push_back(n2);
|
||||
is_checked.push_back(false);
|
||||
}
|
||||
else {
|
||||
args.push_back(arg);
|
||||
|
@ -251,22 +242,16 @@ protected:
|
|||
|
||||
done:
|
||||
if (res) {
|
||||
cache.insert(e, std::make_pair(pos, res));
|
||||
}
|
||||
|
||||
TRACE("ctx_solver_simplify_tactic",
|
||||
tout << mk_pp(e, m) << " checked: " << checked << " cached: " << mk_pp(res?res.get():e, m) << "\n";);
|
||||
cache.insert(e, expr_pos(parent_pos, self_pos, self_idx, res));
|
||||
}
|
||||
|
||||
todo.pop_back();
|
||||
parent_ids.pop_back();
|
||||
self_ids.pop_back();
|
||||
names.pop_back();
|
||||
is_checked.pop_back();
|
||||
m_solver.pop(1);
|
||||
}
|
||||
if (!m_cancel) {
|
||||
VERIFY(cache.find(fml, path_r));
|
||||
result = path_r.second;
|
||||
result = path_r.m_expr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,32 +291,6 @@ protected:
|
|||
}
|
||||
return expr_ref(m.mk_app(fn, m_arith.mk_numeral(rational(id++), true)), m);
|
||||
}
|
||||
|
||||
|
||||
expr_ref local_simplify(app* a, expr* n, unsigned& id, unsigned index) {
|
||||
SASSERT(index < a->get_num_args());
|
||||
SASSERT(m.is_bool(a->get_arg(index)));
|
||||
expr_ref n2(m), result(m), tmp(m);
|
||||
n2 = mk_fresh(id, m.get_sort(a->get_arg(index)));
|
||||
ptr_buffer<expr> args;
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
if (i == index) {
|
||||
args.push_back(n2);
|
||||
}
|
||||
else {
|
||||
args.push_back(a->get_arg(i));
|
||||
}
|
||||
}
|
||||
m_mk_app(a->get_decl(), args.size(), args.c_ptr(), result);
|
||||
m_solver.push();
|
||||
tmp = m.mk_eq(result, n);
|
||||
m_solver.assert_expr(tmp);
|
||||
if (!simplify_bool(n2, result)) {
|
||||
result = a->get_arg(index);
|
||||
}
|
||||
m_solver.pop(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
theory_horn_ineq.h
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-18
|
||||
|
||||
Revision History:
|
||||
|
||||
The implementaton is derived from theory_diff_logic.
|
||||
|
||||
--*/
|
||||
#include "theory_horn_ineq.h"
|
||||
#include "theory_horn_ineq_def.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
template class theory_horn_ineq<ihi_ext>;
|
||||
template class theory_horn_ineq<rhi_ext>;
|
||||
|
||||
// similar to test_diff_logic:
|
||||
|
||||
horn_ineq_tester::horn_ineq_tester(ast_manager& m): m(m), a(m) {}
|
||||
|
||||
bool horn_ineq_tester::operator()(expr* e) {
|
||||
m_todo.reset();
|
||||
m_pols.reset();
|
||||
pos_mark.reset();
|
||||
neg_mark.reset();
|
||||
m_todo.push_back(e);
|
||||
m_pols.push_back(l_true);
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
lbool p = m_pols.back();
|
||||
m_todo.pop_back();
|
||||
m_pols.pop_back();
|
||||
switch (p) {
|
||||
case l_true:
|
||||
if (pos_mark.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
pos_mark.mark(e, true);
|
||||
break;
|
||||
case l_false:
|
||||
if (neg_mark.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
neg_mark.mark(e, true);
|
||||
break;
|
||||
case l_undef:
|
||||
if (pos_mark.is_marked(e) && neg_mark.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
pos_mark.mark(e, true);
|
||||
neg_mark.mark(e, true);
|
||||
break;
|
||||
}
|
||||
if (!test_expr(p, e)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<std::pair<expr*,rational> > const& horn_ineq_tester::get_linearization() const {
|
||||
return m_terms;
|
||||
}
|
||||
|
||||
bool horn_ineq_tester::test_expr(lbool p, expr* e) {
|
||||
expr* e1, *e2, *e3;
|
||||
if (is_var(e)) {
|
||||
return true;
|
||||
}
|
||||
if (!is_app(e)) {
|
||||
return false;
|
||||
}
|
||||
app* ap = to_app(e);
|
||||
if (m.is_and(ap) || m.is_or(ap)) {
|
||||
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
|
||||
m_todo.push_back(ap->get_arg(i));
|
||||
m_pols.push_back(p);
|
||||
}
|
||||
}
|
||||
else if (m.is_not(e, e1)) {
|
||||
m_todo.push_back(e);
|
||||
m_pols.push_back(~p);
|
||||
}
|
||||
else if (m.is_ite(e, e1, e2, e3)) {
|
||||
m_todo.push_back(e1);
|
||||
m_pols.push_back(l_undef);
|
||||
m_todo.push_back(e2);
|
||||
m_pols.push_back(p);
|
||||
m_todo.push_back(e3);
|
||||
m_pols.push_back(p);
|
||||
}
|
||||
else if (m.is_iff(e, e1, e2)) {
|
||||
m_todo.push_back(e1);
|
||||
m_pols.push_back(l_undef);
|
||||
m_todo.push_back(e2);
|
||||
m_pols.push_back(l_undef);
|
||||
m_todo.push_back(e2);
|
||||
}
|
||||
else if (m.is_implies(e, e1, e2)) {
|
||||
m_todo.push_back(e1);
|
||||
m_pols.push_back(~p);
|
||||
m_todo.push_back(e2);
|
||||
m_pols.push_back(p);
|
||||
}
|
||||
else if (m.is_eq(e, e1, e2)) {
|
||||
return linearize(e1, e2) == diff;
|
||||
}
|
||||
else if (m.is_true(e) || m.is_false(e)) {
|
||||
// no-op
|
||||
}
|
||||
else if (a.is_le(e, e1, e2) || a.is_ge(e, e2, e1) ||
|
||||
a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1)) {
|
||||
if (p == l_false) {
|
||||
std::swap(e2, e1);
|
||||
}
|
||||
classify_t cl = linearize(e1, e2);
|
||||
switch(p) {
|
||||
case l_undef:
|
||||
return cl == diff;
|
||||
case l_true:
|
||||
case l_false:
|
||||
return cl == horn || cl == diff;
|
||||
}
|
||||
}
|
||||
else if (!is_uninterp_const(e)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool horn_ineq_tester::operator()(unsigned num_fmls, expr* const* fmls) {
|
||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
||||
if (!(*this)(fmls[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize(expr* e) {
|
||||
m_terms.reset();
|
||||
m_terms.push_back(std::make_pair(e, rational(1)));
|
||||
return linearize();
|
||||
}
|
||||
|
||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize(expr* e1, expr* e2) {
|
||||
m_terms.reset();
|
||||
m_terms.push_back(std::make_pair(e1, rational(1)));
|
||||
m_terms.push_back(std::make_pair(e2, rational(-1)));
|
||||
return linearize();
|
||||
}
|
||||
|
||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize() {
|
||||
|
||||
m_weight.reset();
|
||||
m_coeff_map.reset();
|
||||
|
||||
while (!m_terms.empty()) {
|
||||
expr* e1, *e2;
|
||||
rational num;
|
||||
rational mul = m_terms.back().second;
|
||||
expr* e = m_terms.back().first;
|
||||
m_terms.pop_back();
|
||||
if (a.is_add(e)) {
|
||||
for (unsigned i = 0; i < to_app(e)->get_num_args(); ++i) {
|
||||
m_terms.push_back(std::make_pair(to_app(e)->get_arg(i), mul));
|
||||
}
|
||||
}
|
||||
else if (a.is_mul(e, e1, e2) && a.is_numeral(e1, num)) {
|
||||
m_terms.push_back(std::make_pair(e2, mul*num));
|
||||
}
|
||||
else if (a.is_mul(e, e2, e1) && a.is_numeral(e1, num)) {
|
||||
m_terms.push_back(std::make_pair(e2, mul*num));
|
||||
}
|
||||
else if (a.is_sub(e, e1, e2)) {
|
||||
m_terms.push_back(std::make_pair(e1, mul));
|
||||
m_terms.push_back(std::make_pair(e2, -mul));
|
||||
}
|
||||
else if (a.is_uminus(e, e1)) {
|
||||
m_terms.push_back(std::make_pair(e1, -mul));
|
||||
}
|
||||
else if (a.is_numeral(e, num)) {
|
||||
m_weight += num*mul;
|
||||
}
|
||||
else if (a.is_to_real(e, e1)) {
|
||||
m_terms.push_back(std::make_pair(e1, mul));
|
||||
}
|
||||
else if (!is_uninterp_const(e)) {
|
||||
return non_horn;
|
||||
}
|
||||
else {
|
||||
m_coeff_map.insert_if_not_there2(e, rational(0))->get_data().m_value += mul;
|
||||
}
|
||||
}
|
||||
unsigned num_negative = 0;
|
||||
unsigned num_positive = 0;
|
||||
bool is_unit_pos = true, is_unit_neg = true;
|
||||
obj_map<expr, rational>::iterator it = m_coeff_map.begin();
|
||||
obj_map<expr, rational>::iterator end = m_coeff_map.end();
|
||||
for (; it != end; ++it) {
|
||||
rational r = it->m_value;
|
||||
if (r.is_zero()) {
|
||||
continue;
|
||||
}
|
||||
m_terms.push_back(std::make_pair(it->m_key, r));
|
||||
if (r.is_pos()) {
|
||||
is_unit_pos = is_unit_pos && r.is_one();
|
||||
num_positive++;
|
||||
}
|
||||
else {
|
||||
is_unit_neg = is_unit_neg && r.is_minus_one();
|
||||
num_negative++;
|
||||
}
|
||||
}
|
||||
if (num_negative <= 1 && is_unit_pos && is_unit_neg && num_positive <= 1) {
|
||||
return diff;
|
||||
}
|
||||
if (num_positive <= 1 && is_unit_pos) {
|
||||
return horn;
|
||||
}
|
||||
if (num_negative <= 1 && is_unit_neg) {
|
||||
return co_horn;
|
||||
}
|
||||
return non_horn;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,328 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
theory_horn_ineq.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A*x <= weight + D*x, coefficients to A and D are non-negative,
|
||||
D is a diagonal matrix.
|
||||
Coefficients to weight may have both signs.
|
||||
|
||||
Label variables by weight.
|
||||
Select inequality that is not satisfied.
|
||||
Set delta(LHS) := 0
|
||||
Set delta(RHS(x)) := weight(x) - b
|
||||
Propagate weight increment through inequalities.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-18
|
||||
|
||||
Revision History:
|
||||
|
||||
The implementaton is derived from theory_diff_logic.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _THEORY_HORN_INEQ_H_
|
||||
#define _THEORY_HORN_INEQ_H_
|
||||
|
||||
#include"rational.h"
|
||||
#include"inf_rational.h"
|
||||
#include"inf_int_rational.h"
|
||||
#include"inf_eps_rational.h"
|
||||
#include"smt_theory.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"smt_justification.h"
|
||||
#include"map.h"
|
||||
#include"smt_params.h"
|
||||
#include"arith_eq_adapter.h"
|
||||
#include"smt_model_generator.h"
|
||||
#include"numeral_factory.h"
|
||||
#include"smt_clause.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
class horn_ineq_tester {
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
ptr_vector<expr> m_todo;
|
||||
svector<lbool> m_pols;
|
||||
ast_mark pos_mark, neg_mark;
|
||||
obj_map<expr, rational> m_coeff_map;
|
||||
rational m_weight;
|
||||
vector<std::pair<expr*, rational> > m_terms;
|
||||
|
||||
public:
|
||||
enum classify_t {
|
||||
co_horn,
|
||||
horn,
|
||||
diff,
|
||||
non_horn
|
||||
};
|
||||
horn_ineq_tester(ast_manager& m);
|
||||
|
||||
// test if formula is in the Horn inequality fragment:
|
||||
bool operator()(expr* fml);
|
||||
bool operator()(unsigned num_fmls, expr* const* fmls);
|
||||
|
||||
// linearize inequality/equality
|
||||
classify_t linearize(expr* e);
|
||||
classify_t linearize(expr* e1, expr* e2);
|
||||
|
||||
// retrieve linearization
|
||||
vector<std::pair<expr*,rational> > const& get_linearization() const;
|
||||
rational const& get_weight() const { return m_weight; }
|
||||
private:
|
||||
bool test_expr(lbool p, expr* e);
|
||||
classify_t linearize();
|
||||
};
|
||||
|
||||
template<typename Ext>
|
||||
class theory_horn_ineq : public theory, private Ext {
|
||||
|
||||
typedef typename Ext::numeral numeral;
|
||||
typedef typename Ext::inf_numeral inf_numeral;
|
||||
typedef literal explanation;
|
||||
typedef theory_var th_var;
|
||||
typedef svector<th_var> th_var_vector;
|
||||
typedef unsigned clause_id;
|
||||
typedef vector<std::pair<th_var, rational> > coeffs;
|
||||
|
||||
class clause;
|
||||
class graph;
|
||||
class assignment_trail;
|
||||
class parent_trail;
|
||||
|
||||
class atom {
|
||||
protected:
|
||||
bool_var m_bvar;
|
||||
bool m_true;
|
||||
int m_pos;
|
||||
int m_neg;
|
||||
public:
|
||||
atom(bool_var bv, int pos, int neg) :
|
||||
m_bvar(bv), m_true(false),
|
||||
m_pos(pos), m_neg(neg) {}
|
||||
~atom() {}
|
||||
bool_var get_bool_var() const { return m_bvar; }
|
||||
bool is_true() const { return m_true; }
|
||||
void assign_eh(bool is_true) { m_true = is_true; }
|
||||
int get_asserted_edge() const { return this->m_true?m_pos:m_neg; }
|
||||
int get_pos() const { return m_pos; }
|
||||
int get_neg() const { return m_neg; }
|
||||
std::ostream& display(theory_horn_ineq const& th, std::ostream& out) const;
|
||||
};
|
||||
typedef svector<atom> atoms;
|
||||
|
||||
struct scope {
|
||||
unsigned m_atoms_lim;
|
||||
unsigned m_asserted_atoms_lim;
|
||||
unsigned m_asserted_qhead_old;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
unsigned m_num_conflicts;
|
||||
unsigned m_num_assertions;
|
||||
unsigned m_num_core2th_eqs;
|
||||
unsigned m_num_core2th_diseqs;
|
||||
|
||||
void reset() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
stats() {
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
stats m_stats;
|
||||
smt_params m_params;
|
||||
arith_util a;
|
||||
arith_eq_adapter m_arith_eq_adapter;
|
||||
th_var m_zero_int; // cache the variable representing the zero variable.
|
||||
th_var m_zero_real; // cache the variable representing the zero variable.
|
||||
|
||||
graph* m_graph;
|
||||
atoms m_atoms;
|
||||
unsigned_vector m_asserted_atoms; // set of asserted atoms
|
||||
unsigned m_asserted_qhead;
|
||||
u_map<unsigned> m_bool_var2atom;
|
||||
svector<scope> m_scopes;
|
||||
|
||||
double m_agility;
|
||||
bool m_lia;
|
||||
bool m_lra;
|
||||
bool m_non_horn_ineq_exprs;
|
||||
|
||||
horn_ineq_tester m_test;
|
||||
|
||||
|
||||
arith_factory * m_factory;
|
||||
rational m_delta;
|
||||
rational m_lambda;
|
||||
|
||||
|
||||
// Set a conflict due to a negative cycle.
|
||||
void set_neg_cycle_conflict();
|
||||
|
||||
// Create a new theory variable.
|
||||
virtual th_var mk_var(enode* n);
|
||||
|
||||
virtual th_var mk_var(expr* n);
|
||||
|
||||
void compute_delta();
|
||||
|
||||
void found_non_horn_ineq_expr(expr * n);
|
||||
|
||||
bool is_interpreted(app* n) const {
|
||||
return n->get_family_id() == get_family_id();
|
||||
}
|
||||
|
||||
public:
|
||||
theory_horn_ineq(ast_manager& m);
|
||||
|
||||
virtual ~theory_horn_ineq();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_horn_ineq, get_manager()); }
|
||||
|
||||
virtual char const * get_name() const { return "horn-inequality-logic"; }
|
||||
|
||||
/**
|
||||
\brief See comment in theory::mk_eq_atom
|
||||
*/
|
||||
virtual app * mk_eq_atom(expr * lhs, expr * rhs) { return a.mk_eq(lhs, rhs); }
|
||||
|
||||
virtual void init(context * ctx);
|
||||
|
||||
virtual bool internalize_atom(app * atom, bool gate_ctx);
|
||||
|
||||
virtual bool internalize_term(app * term);
|
||||
|
||||
virtual void internalize_eq_eh(app * atom, bool_var v);
|
||||
|
||||
virtual void assign_eh(bool_var v, bool is_true);
|
||||
|
||||
virtual void new_eq_eh(th_var v1, th_var v2) {
|
||||
m_arith_eq_adapter.new_eq_eh(v1, v2);
|
||||
}
|
||||
|
||||
virtual bool use_diseqs() const { return true; }
|
||||
|
||||
virtual void new_diseq_eh(th_var v1, th_var v2) {
|
||||
m_arith_eq_adapter.new_diseq_eh(v1, v2);
|
||||
}
|
||||
|
||||
virtual void push_scope_eh();
|
||||
|
||||
virtual void pop_scope_eh(unsigned num_scopes);
|
||||
|
||||
virtual void restart_eh() {
|
||||
m_arith_eq_adapter.restart_eh();
|
||||
}
|
||||
|
||||
virtual void relevant_eh(app* e) {}
|
||||
|
||||
virtual void init_search_eh() {
|
||||
m_arith_eq_adapter.init_search_eh();
|
||||
}
|
||||
|
||||
virtual final_check_status final_check_eh();
|
||||
|
||||
virtual bool is_shared(th_var v) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool can_propagate() {
|
||||
SASSERT(m_asserted_qhead <= m_asserted_atoms.size());
|
||||
return m_asserted_qhead != m_asserted_atoms.size();
|
||||
}
|
||||
|
||||
virtual void propagate();
|
||||
|
||||
virtual justification * why_is_diseq(th_var v1, th_var v2) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void reset_eh();
|
||||
|
||||
virtual void init_model(model_generator & m);
|
||||
|
||||
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
||||
|
||||
virtual bool validate_eq_in_model(th_var v1, th_var v2, bool is_true) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void display(std::ostream & out) const;
|
||||
|
||||
virtual void collect_statistics(::statistics & st) const;
|
||||
|
||||
private:
|
||||
|
||||
virtual void new_eq_eh(th_var v1, th_var v2, justification& j) {
|
||||
m_stats.m_num_core2th_eqs++;
|
||||
new_eq_or_diseq(true, v1, v2, j);
|
||||
}
|
||||
|
||||
virtual void new_diseq_eh(th_var v1, th_var v2, justification& j) {
|
||||
m_stats.m_num_core2th_diseqs++;
|
||||
new_eq_or_diseq(false, v1, v2, j);
|
||||
}
|
||||
|
||||
void negate(coeffs& coeffs, rational& weight);
|
||||
numeral mk_weight(bool is_real, bool is_strict, rational const& w) const;
|
||||
void mk_coeffs(vector<std::pair<expr*,rational> >const& terms, coeffs& coeffs, rational& w);
|
||||
|
||||
void del_atoms(unsigned old_size);
|
||||
|
||||
void propagate_core();
|
||||
|
||||
bool propagate_atom(atom const& a);
|
||||
|
||||
th_var mk_term(app* n);
|
||||
|
||||
th_var mk_num(app* n, rational const& r);
|
||||
|
||||
bool is_consistent() const;
|
||||
|
||||
th_var expand(bool pos, th_var v, rational & k);
|
||||
|
||||
void new_eq_or_diseq(bool is_eq, th_var v1, th_var v2, justification& eq_just);
|
||||
|
||||
th_var get_zero(sort* s) const { return a.is_int(s)?m_zero_int:m_zero_real; }
|
||||
|
||||
th_var get_zero(expr* e) const { return get_zero(get_manager().get_sort(e)); }
|
||||
|
||||
void inc_conflicts();
|
||||
|
||||
};
|
||||
|
||||
struct rhi_ext {
|
||||
typedef inf_rational inf_numeral;
|
||||
typedef inf_eps_rational<inf_rational> numeral;
|
||||
numeral m_epsilon;
|
||||
numeral m_minus_infty;
|
||||
rhi_ext() : m_epsilon(inf_rational(rational(), true)), m_minus_infty(rational(-1),inf_rational()) {}
|
||||
};
|
||||
|
||||
struct ihi_ext {
|
||||
typedef rational inf_numeral;
|
||||
typedef inf_eps_rational<rational> numeral;
|
||||
numeral m_epsilon;
|
||||
numeral m_minus_infty;
|
||||
ihi_ext() : m_epsilon(rational(1)), m_minus_infty(rational(-1),rational(0)) {}
|
||||
};
|
||||
|
||||
typedef theory_horn_ineq<rhi_ext> theory_rhi;
|
||||
typedef theory_horn_ineq<ihi_ext> theory_ihi;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _THEORY_HORN_INEQ_H_ */
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue