3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

move theory_var_list into id_var_list and utilities from smt-enode into it, prepare for theory variables in egraph

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-09-01 04:26:31 -07:00
parent fa9cf0fa0c
commit d4e92d4aca
11 changed files with 332 additions and 193 deletions

View file

@ -781,10 +781,10 @@ namespace smt {
if (r2->m_th_var_list.get_next() == nullptr && r1->m_th_var_list.get_next() == nullptr) {
// Common case: r2 and r1 have at most one theory var.
theory_id t2 = r2->m_th_var_list.get_th_id();
theory_id t1 = r1->m_th_var_list.get_th_id();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t2) : r2->m_th_var_list.get_th_var();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : r1->m_th_var_list.get_th_var();
theory_id t2 = r2->m_th_var_list.get_id();
theory_id t1 = r1->m_th_var_list.get_id();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t2) : r2->m_th_var_list.get_var();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : r1->m_th_var_list.get_var();
TRACE("merge_theory_vars",
tout << "v2: " << v2 << " #" << r2->get_owner_id() << ", v1: " << v1 << " #" << r1->get_owner_id()
<< ", t2: " << t2 << ", t1: " << t1 << "\n";);
@ -805,8 +805,8 @@ namespace smt {
push_new_th_diseqs(r1, v2, get_theory(t2));
}
else if (v1 != null_theory_var && v2 == null_theory_var) {
r2->m_th_var_list.set_th_var(v1);
r2->m_th_var_list.set_th_id(t1);
r2->m_th_var_list.set_var(v1);
r2->m_th_var_list.set_id(t1);
TRACE("merge_theory_vars", tout << "push_new_th_diseqs v1: " << v1 << ", t1: " << t1 << "\n";);
push_new_th_diseqs(r2, v1, get_theory(t1));
}
@ -819,8 +819,8 @@ namespace smt {
theory_var_list * l2 = r2->get_th_var_list();
while (l2) {
theory_id t2 = l2->get_th_id();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t2) : l2->get_th_var();
theory_id t2 = l2->get_id();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t2) : l2->get_var();
SASSERT(v2 != null_theory_var);
SASSERT(t2 != null_theory_id);
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t2) : r1->get_th_var(t2);
@ -838,8 +838,8 @@ namespace smt {
theory_var_list * l1 = r1->get_th_var_list();
while (l1) {
theory_id t1 = l1->get_th_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : l1->get_th_var();
theory_id t1 = l1->get_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : l1->get_var();
SASSERT(v1 != null_theory_var);
SASSERT(t1 != null_theory_id);
theory_var v2 = r2->get_th_var(t1);
@ -973,13 +973,13 @@ namespace smt {
// restore theory vars
if (r2->m_th_var_list.get_next() == nullptr) {
// common case: r2 has at most one variable
theory_var v2 = r2->m_th_var_list.get_th_var();
theory_var v2 = r2->m_th_var_list.get_var();
if (v2 != null_theory_var) {
theory_id t2 = r2->m_th_var_list.get_th_id();
theory_id t2 = r2->m_th_var_list.get_id();
if (get_theory(t2)->get_enode(v2)->get_root() != r2) {
SASSERT(get_theory(t2)->get_enode(v2)->get_root() == r1);
r2->m_th_var_list.set_th_var(null_theory_var); //remove variable from r2
r2->m_th_var_list.set_th_id(null_theory_id);
r2->m_th_var_list.set_var(null_theory_var); //remove variable from r2
r2->m_th_var_list.set_id(null_theory_id);
}
}
}
@ -1019,8 +1019,8 @@ namespace smt {
theory_var_list * new_l2 = nullptr;
theory_var_list * l2 = r2->get_th_var_list();
while (l2) {
theory_var v2 = l2->get_th_var();
theory_id t2 = l2->get_th_id();
theory_var v2 = l2->get_var();
theory_id t2 = l2->get_id();
if (get_theory(t2)->get_enode(v2)->get_root() != r2) {
SASSERT(get_theory(t2)->get_enode(v2)->get_root() == r1);
@ -1043,7 +1043,7 @@ namespace smt {
new_l2->set_next(nullptr);
}
else {
r2->m_th_var_list.set_th_var(null_theory_var);
r2->m_th_var_list.set_var(null_theory_var);
r2->m_th_var_list.set_next(nullptr);
}
}
@ -1070,7 +1070,7 @@ namespace smt {
TRACE("add_diseq_inconsistent", tout << "add_diseq #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " inconsistency, scope_lvl: " << m_scope_lvl << "\n";);
//return false;
theory_id t1 = r1->m_th_var_list.get_th_id();
theory_id t1 = r1->m_th_var_list.get_id();
if (t1 == null_theory_id) return false;
return get_theory(t1)->use_diseqs();
}
@ -1078,15 +1078,15 @@ namespace smt {
// Propagate disequalities to theories
if (r1->m_th_var_list.get_next() == nullptr && r2->m_th_var_list.get_next() == nullptr) {
// common case: r2 and r1 have at most one theory var.
theory_id t1 = r1->m_th_var_list.get_th_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : r1->m_th_var_list.get_th_var();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t1) : r2->m_th_var_list.get_th_var();
theory_id t1 = r1->m_th_var_list.get_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : r1->m_th_var_list.get_var();
theory_var v2 = m_fparams.m_new_core2th_eq ? get_closest_var(n2, t1) : r2->m_th_var_list.get_var();
TRACE("add_diseq", tout << "one theory diseq\n";
tout << v1 << " != " << v2 << "\n";
tout << "th1: " << t1 << " th2: " << r2->m_th_var_list.get_th_id() << "\n";
tout << "th1: " << t1 << " th2: " << r2->m_th_var_list.get_id() << "\n";
);
if (t1 != null_theory_id && v1 != null_theory_var && v2 != null_theory_var &&
t1 == r2->m_th_var_list.get_th_id()) {
t1 == r2->m_th_var_list.get_id()) {
if (get_theory(t1)->use_diseqs())
push_new_th_diseq(t1, v1, v2);
}
@ -1094,8 +1094,8 @@ namespace smt {
else {
theory_var_list * l1 = r1->get_th_var_list();
while (l1) {
theory_id t1 = l1->get_th_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : l1->get_th_var();
theory_id t1 = l1->get_id();
theory_var v1 = m_fparams.m_new_core2th_eq ? get_closest_var(n1, t1) : l1->get_var();
theory * th = get_theory(t1);
TRACE("add_diseq", tout << m.get_family_name(t1) << "\n";);
if (th->use_diseqs()) {
@ -1586,7 +1586,7 @@ namespace smt {
enode * e = get_enode(n);
theory_var_list * l = e->get_th_var_list();
while (l) {
theory_id th_id = l->get_th_id();
theory_id th_id = l->get_id();
theory * th = get_theory(th_id);
// I don't want to invoke relevant_eh twice for the same n.
if (th != propagated_th)
@ -4509,7 +4509,7 @@ namespace smt {
// contains a parent application.
theory_var_list * l = n->get_th_var_list();
theory_id th_id = l->get_th_id();
theory_id th_id = l->get_id();
for (enode * parent : enode::parents(n)) {
app* p = parent->get_owner();
@ -4548,7 +4548,7 @@ namespace smt {
// the theories of (array int int) and (array (array int int) int).
// Remark: The inconsistency is not going to be detected if they are
// not marked as shared.
return get_theory(th_id)->is_shared(l->get_th_var());
return get_theory(th_id)->is_shared(l->get_var());
}
default:
return true;

View file

@ -282,7 +282,7 @@ namespace smt {
<< mk_pp(m.get_sort(lhs->get_owner()), m) << "\n";);
theory_var_list * l = lhs->get_th_var_list();
while (l) {
theory_id th_id = l->get_th_id();
theory_id th_id = l->get_id();
theory * th = get_theory(th_id);
TRACE("check_th_diseq_propagation", tout << "checking theory: " << m.get_family_name(th_id) << "\n";);
// if the theory doesn't use diseqs, then the diseqs are not propagated.

View file

@ -93,13 +93,7 @@ namespace smt {
}
unsigned enode::get_num_th_vars() const {
unsigned r = 0;
theory_var_list const * l = get_th_var_list();
while(l) {
r++;
l = l->get_next();
}
return r;
return m_th_var_list.size();
}
/**
@ -109,44 +103,14 @@ namespace smt {
with a variable of theory th_id
*/
theory_var enode::get_th_var(theory_id th_id) const {
if (m_th_var_list.get_th_var() == null_theory_var)
return null_theory_var;
theory_var_list const * l = &m_th_var_list;
while (l) {
if (l->get_th_id() == th_id) {
return l->get_th_var();
}
l = l->get_next();
}
return null_theory_var;
return m_th_var_list.find(th_id);
}
/**
\brief Add the entry (v, id) to the list of theory variables.
*/
void enode::add_th_var(theory_var v, theory_id id, region & r) {
#ifdef Z3DEBUG
unsigned old_size = get_num_th_vars();
#endif
SASSERT(get_th_var(id) == null_theory_var);
if (m_th_var_list.get_th_var() == null_theory_var) {
m_th_var_list.set_th_var(v);
m_th_var_list.set_th_id(id);
m_th_var_list.set_next(nullptr);
}
else {
theory_var_list * l = &m_th_var_list;
while (l->get_next() != nullptr) {
SASSERT(l->get_th_id() != id);
l = l->get_next();
}
SASSERT(l);
SASSERT(l->get_next() == 0);
theory_var_list * new_cell = new (r) theory_var_list(id, v);
l->set_next(new_cell);
}
SASSERT(get_num_th_vars() == old_size + 1);
SASSERT(get_th_var(id) == v);
m_th_var_list.add_var(v, id, r);
}
/**
@ -154,16 +118,7 @@ namespace smt {
The enode must have an entry (v', id)
*/
void enode::replace_th_var(theory_var v, theory_id id) {
SASSERT(get_th_var(id) != null_theory_var);
theory_var_list * l = get_th_var_list();
while (l) {
if (l->get_th_id() == id) {
l->set_th_var(v);
return;
}
l = l->get_next();
}
UNREACHABLE();
m_th_var_list.replace(v, id);
}
/**
@ -171,33 +126,7 @@ namespace smt {
enode is associated with a variable of the given theory.
*/
void enode::del_th_var(theory_id id) {
SASSERT(get_th_var(id) != null_theory_var);
if (m_th_var_list.get_th_id() == id) {
theory_var_list * next = m_th_var_list.get_next();
if (next == nullptr) {
// most common case
m_th_var_list.set_th_var(null_theory_var);
m_th_var_list.set_th_id(null_theory_id);
m_th_var_list.set_next(nullptr);
}
else {
m_th_var_list = *next;
}
}
else {
theory_var_list * prev = get_th_var_list();
theory_var_list * l = prev->get_next();
while (l) {
SASSERT(prev->get_next() == l);
if (l->get_th_id() == id) {
prev->set_next(l->get_next());
return;
}
prev = l;
l = l->get_next();
}
UNREACHABLE();
}
m_th_var_list.del_var(id);
}

View file

@ -18,11 +18,12 @@ Revision History:
--*/
#pragma once
#include "util/id_var_list.h"
#include "util/approx_set.h"
#include "ast/ast.h"
#include "smt/smt_types.h"
#include "smt/smt_eq_justification.h"
#include "smt/smt_theory_var_list.h"
#include "util/approx_set.h"
namespace smt {
@ -48,6 +49,7 @@ namespace smt {
unknown performance penalty for this. */
typedef ptr_vector<enode> app2enode_t; // app -> enode
typedef id_var_list<null_family_id, null_theory_var> theory_var_list;
class tmp_enode;
@ -91,7 +93,7 @@ namespace smt {
then the congruent f(b) in m_parents will also be relevant.
*/
enode_vector m_parents; //!< Parent enodes of the equivalence class.
theory_var_list m_th_var_list; //!< List of theories that 'care' about this enode.
id_var_list<> m_th_var_list; //!< List of theories that 'care' about this enode.
trans_justification m_trans; //!< A justification for the enode being equal to its root.
bool m_proof_is_logged; //!< Indicates that the proof for the enode being equal to its root is in the log.
signed char m_lbl_hash; //!< It is different from -1, if enode is used in a pattern
@ -105,7 +107,7 @@ namespace smt {
theory_var_list * get_th_var_list() {
return m_th_var_list.get_th_var() == null_theory_var ? nullptr : &m_th_var_list;
return m_th_var_list.get_var() == null_theory_var ? nullptr : &m_th_var_list;
}
friend class set_merge_tf_trail;
@ -356,11 +358,11 @@ namespace smt {
iterator end() { return iterator(this, this); }
theory_var_list const * get_th_var_list() const {
return m_th_var_list.get_th_var() == null_theory_var ? nullptr : &m_th_var_list;
return m_th_var_list.get_var() == null_theory_var ? nullptr : &m_th_var_list;
}
bool has_th_vars() const {
return m_th_var_list.get_th_var() != null_theory_var;
return m_th_var_list.get_var() != null_theory_var;
}
unsigned get_num_th_vars() const;

View file

@ -1,74 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smt_theory_var_list.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-02-19.
Revision History:
--*/
#pragma once
#include "smt/smt_types.h"
namespace smt {
class theory_var_list {
int m_th_id:8;
int m_th_var:24;
theory_var_list * m_next;
public:
theory_var_list():
m_th_id(null_theory_id),
m_th_var(null_theory_var),
m_next(nullptr) {
}
theory_var_list(theory_id t, theory_var v, theory_var_list * n = nullptr):
m_th_id(t),
m_th_var(v),
m_next(n) {
}
theory_id get_th_id() const {
return m_th_id;
}
theory_var get_th_var() const {
return m_th_var;
}
theory_var_list * get_next() const {
return m_next;
}
void set_th_id(theory_id id) {
m_th_id = id;
}
void set_th_var(theory_var v) {
m_th_var = v;
}
void set_next(theory_var_list * next) {
m_next = next;
}
};
// 32 bit machine
static_assert(sizeof(expr*) != 4 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int), "32 bit");
// 64 bit machine
static_assert(sizeof(expr*) != 8 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int) + /* a structure must be aligned */ sizeof(int), "64 bit");
};

View file

@ -498,7 +498,7 @@ namespace smt {
TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";);
r->set_mark();
to_unmark.push_back(r);
theory_var r_th_var = r->get_th_var(get_id());
theory_var r_th_var = r->get_var(get_id());
SASSERT(r_th_var != null_theory_var);
result.push_back(r_th_var);
}