3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
z3/lib/smt_enode.h
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

383 lines
12 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smt_enode.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-02-18.
Revision History:
--*/
#ifndef _SMT_ENODE_H_
#define _SMT_ENODE_H_
#include"ast.h"
#include"smt_types.h"
#include"smt_eq_justification.h"
#include"smt_theory_var_list.h"
#include"approx_set.h"
namespace smt {
/**
\brief Justification for the transitivity rule.
*/
struct trans_justification {
enode * m_target;
eq_justification m_justification;
trans_justification():
m_target(0),
m_justification(null_eq_justification) {
}
};
class tmp_enode;
/**
\brief Aditional data-structure for implementing congruence closure,
equality propagation, and the theory central bus of equalities.
*/
class enode {
app * m_owner; //!< The application that 'owns' this enode.
enode * m_root; //!< Representative of the equivalence class
enode * m_next; //!< Next element in the equivalence class.
enode * m_cg;
unsigned m_class_size; //!< Size of the equivalence class if the enode is the root.
unsigned m_generation; //!< Tracks how many quantifier instantiation rounds were needed to generate this enode.
unsigned m_func_decl_id; //!< Id generated by the congruence table for fast indexing.
unsigned m_mark:1; //!< Multi-purpose auxiliary mark.
unsigned m_mark2:1; //!< Multi-purpose auxiliary mark.
unsigned m_interpreted:1; //!< True if the node is an interpreted constant.
unsigned m_suppress_args:1; //!< True if the arguments of m_owner should not be accessed by this enode.
unsigned m_eq:1; //!< True if it is an equality
unsigned m_commutative:1; //!< True if commutative app
unsigned m_bool:1; //!< True if it is a boolean enode
unsigned m_merge_tf:1; //!< True if the enode should be merged with true/false when the associated boolean variable is assigned.
unsigned m_cgc_enabled:1; //!< True if congruence closure is enabled for this enode.
unsigned m_iscope_lvl; //!< When the enode was internalized
/*
The following property is valid for m_parents
If this = m_root, then for every term f(a) such that a->get_root() == m_root,
there is a f(b) in m_parents such that b->get_root() == m_root, and f(a) and f(b) are
congruent.
Remark: f(a) and f(b) may have other arguments.
Exception: If f(a) and f(b) are terms of the form (= a c) and (= b d), then
m_parents will not contains (= b d) if b->get_root() == d->get_root().
Remark regarding relevancy propagation: relevancy is propagated to all
elements of an equivalence class. So, if there is a f(a) that is relevant,
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.
trans_justification m_trans; //!< A justification for the enode being equal to its root.
char m_lbl_hash; //!< It is different from -1, if enode is used in a pattern
approx_set m_lbls;
approx_set m_plbls;
enode * m_args[0]; //!< Cached args
friend class context;
friend class euf_manager;
friend class conflict_resolution;
theory_var_list * get_th_var_list() {
return m_th_var_list.get_th_var() == null_theory_var ? 0 : &m_th_var_list;
}
friend class set_merge_tf_trail;
/**
\brief Return true if the enode should be merged with the true (false) enodes when
the associated boolean variable is assigned to true (false).
*/
bool merge_tf() const {
return m_merge_tf;
}
friend class add_th_var_trail;
friend class replace_th_var_trail;
void add_th_var(theory_var v, theory_id id, region & r);
void replace_th_var(theory_var v, theory_id id);
void del_th_var(theory_id id);
friend class tmp_enode;
static enode * init(ast_manager & m, void * mem, ptr_vector<enode> const & app2enode, app * owner,
unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl,
bool cgc_enabled, bool update_children_parent);
public:
static unsigned get_enode_size(unsigned num_args) {
return sizeof(enode) + num_args * sizeof(enode*);
}
static enode * mk(ast_manager & m, region & r, ptr_vector<enode> const & app2enode, app * owner,
unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl,
bool cgc_enabled, bool update_children_parent);
static enode * mk_dummy(ast_manager & m, ptr_vector<enode> const & app2enode, app * owner);
static void del_dummy(enode * n) { dealloc_svect(reinterpret_cast<char*>(n)); }
unsigned get_func_decl_id() const {
return m_func_decl_id;
}
void set_func_decl_id(unsigned id) {
m_func_decl_id = id;
}
void mark_as_interpreted() {
SASSERT(!m_interpreted);
SASSERT(m_owner->get_num_args() == 0);
SASSERT(m_class_size == 1);
m_interpreted = true;
}
void del_eh(ast_manager & m, bool update_children_parent = true);
app * get_owner() const {
return m_owner;
}
unsigned get_owner_id() const {
return m_owner->get_id();
}
func_decl * get_decl() const {
return m_owner->get_decl();
}
unsigned get_decl_id() const {
return m_owner->get_decl()->get_decl_id();
}
unsigned hash() const {
return m_owner->hash();
}
enode * get_root() const {
return m_root;
}
enode * get_next() const {
return m_next;
}
unsigned get_num_args() const {
return m_suppress_args ? 0 : m_owner->get_num_args();
}
enode * get_arg(unsigned idx) const {
SASSERT(idx < get_num_args());
return m_args[idx];
}
enode * const * get_args() const {
return m_args;
}
// unsigned get_id() const {
// return m_id;
// }
unsigned get_class_size() const {
return m_class_size;
}
bool is_bool() const {
return m_bool;
}
bool is_eq() const {
return m_eq;
}
bool is_true_eq() const {
return m_eq && get_arg(0)->get_root() == get_arg(1)->get_root();
}
bool is_marked() const {
return m_mark;
}
void set_mark() {
SASSERT(!m_mark); m_mark = true;
}
void unset_mark() {
SASSERT(m_mark); m_mark = false;
}
bool is_marked2() const {
return m_mark2;
}
void set_mark2() {
SASSERT(!m_mark2); m_mark2 = true;
}
void unset_mark2() {
SASSERT(m_mark2); m_mark2 = false;
}
bool is_interpreted() const {
return m_interpreted;
}
/**
\brief Return true if node is not a constant and it is the root of its congruence class.
\remark if get_num_args() == 0, then is_cgr() = false.
*/
bool is_cgr() const {
return m_cg == this;
}
enode * get_cg() const {
return m_cg;
}
bool is_cgc_enabled() const {
return m_cgc_enabled;
}
bool is_commutative() const {
return m_commutative;
}
unsigned get_num_parents() const {
return m_parents.size();
}
enode_vector::iterator begin_parents() {
return m_parents.begin();
}
enode_vector::iterator end_parents() {
return m_parents.end();
}
enode_vector::const_iterator begin_parents() const {
return m_parents.begin();
}
enode_vector::const_iterator end_parents() const {
return m_parents.end();
}
theory_var_list const * get_th_var_list() const {
return m_th_var_list.get_th_var() == null_theory_var ? 0 : &m_th_var_list;
}
bool has_th_vars() const {
return m_th_var_list.get_th_var() != null_theory_var;
}
unsigned get_num_th_vars() const;
theory_var get_th_var(theory_id th_id) const;
unsigned get_generation() const {
return m_generation;
}
void set_generation(context & ctx, unsigned generation);
/**
\brief Return the enode n that is in the eqc of *this, and has the minimal generation.
That is, there is no other enode with smaller generation.
*/
enode * get_eq_enode_with_min_gen();
unsigned get_iscope_lvl() const {
return m_iscope_lvl;
}
void set_lbl_hash(context & ctx);
bool has_lbl_hash() const {
return m_lbl_hash >= 0;
}
unsigned char get_lbl_hash() const {
SASSERT(m_lbl_hash >= 0 && static_cast<unsigned>(m_lbl_hash) < approx_set_traits<unsigned long long>::capacity);
return static_cast<unsigned char>(m_lbl_hash);
}
approx_set & get_lbls() {
return m_lbls;
}
approx_set & get_plbls() {
return m_plbls;
}
const approx_set & get_lbls() const {
return m_lbls;
}
const approx_set & get_plbls() const {
return m_plbls;
}
void display_lbls(std::ostream & out) const;
#ifdef Z3DEBUG
bool check_invariant() const;
bool trans_reaches(enode * n) const;
bool check_parent_invariant() const;
bool contains_parent_congruent_to(enode * p) const;
#endif
};
inline bool same_eqc(enode const * n1 , enode const * n2) { return n1->get_root() == n2->get_root(); }
/**
\brief Return true, if n1 and n2 are congruent.
Set comm to true, if the nodes are congruent modulo commutativity.
*/
bool congruent(enode * n1, enode * n2, bool & comm);
inline bool congruent(enode * n1, enode * n2) {
bool aux;
return congruent(n1, n2, aux);
}
unsigned get_max_generation(unsigned num_enodes, enode * const * enodes);
void unmark_enodes(unsigned num_enodes, enode * const * enodes);
void unmark_enodes2(unsigned num_enodes, enode * const * enodes);
class tmp_enode {
tmp_app m_app;
unsigned m_capacity;
char * m_enode_data;
enode * get_enode() { return reinterpret_cast<enode*>(m_enode_data); }
void set_capacity(unsigned new_capacity);
public:
tmp_enode();
~tmp_enode();
enode * set(func_decl * f, unsigned num_args, enode * const * args);
void reset();
};
};
#endif /* _SMT_ENODE_H_ */