mirror of
https://github.com/Z3Prover/z3
synced 2025-08-14 06:45:25 +00:00
use z3's egraph (wip)
This commit is contained in:
parent
d8d8c67a3b
commit
0fb81fc437
2 changed files with 156 additions and 193 deletions
|
@ -50,13 +50,24 @@ namespace polysat {
|
|||
using dep_t = sat::literal;
|
||||
using dep_vector = sat::literal_vector;
|
||||
static constexpr sat::literal null_dep = sat::null_literal;
|
||||
void* encode_dep(dep_t d);
|
||||
dep_t decode_dep(void* d);
|
||||
|
||||
using slice = unsigned;
|
||||
using slice_vector = unsigned_vector;
|
||||
static constexpr slice null_slice = std::numeric_limits<slice>::max();
|
||||
static constexpr slice null_slice = std::numeric_limits<slice>::max();
|
||||
|
||||
static constexpr unsigned null_cut = std::numeric_limits<unsigned>::max();
|
||||
|
||||
struct slice_info {
|
||||
unsigned width = 0;
|
||||
unsigned cut = null_cut;
|
||||
euf::enode* sub_hi = nullptr;
|
||||
euf::enode* sub_lo = nullptr;
|
||||
};
|
||||
|
||||
// using enode = euf::enode<slice_extra>;
|
||||
|
||||
struct val2slice_key {
|
||||
rational value;
|
||||
unsigned bit_width;
|
||||
|
@ -76,33 +87,26 @@ namespace polysat {
|
|||
using val2slice_eq = default_eq<val2slice_key>;
|
||||
using val2slice_map = map<val2slice_key, slice, val2slice_hash, val2slice_eq>;
|
||||
|
||||
// number of bits in the slice
|
||||
unsigned_vector m_slice_width;
|
||||
unsigned_vector m_slice_width; // number of bits in the slice
|
||||
// Cut point: if slice represents bit-vector x, then x has been sliced into x[|x|-1:cut+1] and x[cut:0].
|
||||
// The cut point is relative to the parent slice (rather than a root variable, which might not be unique)
|
||||
// (null_cut for leaf slices)
|
||||
unsigned_vector m_slice_cut;
|
||||
// The sub-slices are at indices sub and sub+1 (or null_slice if there is no subdivision)
|
||||
slice_vector m_slice_sub;
|
||||
slice_vector m_find; // representative of equivalence class
|
||||
slice_vector m_size; // number of elements in equivalence class
|
||||
slice_vector m_next; // next element of the equivalence class
|
||||
|
||||
slice_vector m_proof_parent; // the proof forest
|
||||
dep_vector m_proof_reason; // justification for merge of an element with its parent (in the proof forest)
|
||||
|
||||
// unsigned_vector m_value_id; // slice -> value id
|
||||
// vector<rational> m_value; // id -> value
|
||||
// slice_vector m_value_root; // the slice representing the associated value, if any. NOTE: subslices will inherit this from their parents.
|
||||
// TODO: value_root probably not necessary.
|
||||
// but we will need to create value slices for the sub-slices.
|
||||
// then the "reason" for that equality must be a marker "equality between parent and its value". explanation at that point must go up recursively.
|
||||
vector<rational> m_slice2val; // slice -> value (-1 if none)
|
||||
val2slice_map m_val2slice; // (value, bit-width) -> slice
|
||||
|
||||
pvar_vector m_slice2var; // slice -> pvar, or null_var if slice is not equivalent to a variable
|
||||
slice_vector m_var2slice; // pvar -> slice
|
||||
|
||||
// app_ref_vector m_slice2app; // slice -> app*
|
||||
// ptr_addr_map<app, slice> m_app2slice;
|
||||
|
||||
ptr_vector<euf::enode> m_slice2enode;
|
||||
ptr_addr_map<euf::enode, slice> m_enode2slice;
|
||||
expr_ref_vector m_expr_storage;
|
||||
unsigned_vector m_expr_scopes;
|
||||
|
||||
#if 0
|
||||
unsigned_vector m_mark;
|
||||
unsigned m_mark_timestamp = 0;
|
||||
#if Z3DEBUG
|
||||
|
@ -118,27 +122,42 @@ namespace polysat {
|
|||
void end_mark() { DEBUG_CODE({ SASSERT(m_mark_active); m_mark_active = false; }); }
|
||||
bool is_marked(slice s) const { SASSERT(m_mark_active); return m_mark[s] == m_mark_timestamp; }
|
||||
void mark(slice s) { SASSERT(m_mark_active); m_mark[s] = m_mark_timestamp; }
|
||||
#endif
|
||||
|
||||
slice alloc_slice();
|
||||
slice alloc_slice(unsigned width);
|
||||
|
||||
slice var2slice(pvar v) const { return m_var2slice[v]; }
|
||||
pvar slice2var(slice s) const { return m_slice2var[s]; }
|
||||
// slice app2slice(app* a) const { return m_app2slice[a]; }
|
||||
// app* slice2app(slice s) const { return m_slice2app[s]; }
|
||||
slice enode2slice(euf::enode* n) const { return m_enode2slice[n]; }
|
||||
euf::enode* slice2enode(slice s) const { return m_slice2enode[s]; }
|
||||
|
||||
slice var2slice(pvar v) const { return find(m_var2slice[v]); }
|
||||
pvar slice2var(slice s) const { return m_slice2var[find(s)]; }
|
||||
unsigned width(slice s) const { return m_slice_width[s]; }
|
||||
|
||||
bool has_sub(slice s) const { return m_slice_sub[s] != null_slice; }
|
||||
/// Upper subslice (direct child, not necessarily the representative)
|
||||
slice sub_hi(slice s) const;
|
||||
euf::enode* sub_hi(euf::enode* n) const;
|
||||
/// Lower subslice (direct child, not necessarily the representative)
|
||||
slice sub_lo(slice s) const;
|
||||
euf::enode* sub_lo(euf::enode* n) const;
|
||||
|
||||
// slice val2slice(rational const& val, unsigned bit_width) const;
|
||||
|
||||
// Retrieve (or create) a slice representing the given value.
|
||||
slice mk_value_slice(rational const& val, unsigned bit_width);
|
||||
// slice mk_value_slice(rational const& val, unsigned bit_width);
|
||||
|
||||
bool has_value(slice s) const { SASSERT_EQ(s, find(s)); return m_slice2val[s].is_nonneg(); }
|
||||
rational const& get_value(slice s) const { SASSERT(has_value(s)); return m_slice2val[s]; }
|
||||
// bool has_value(slice s) const { SASSERT_EQ(s, find(s)); return m_slice2val[s].is_nonneg(); }
|
||||
// rational const& get_value(slice s) const { SASSERT(has_value(s)); return m_slice2val[s]; }
|
||||
|
||||
// reverse all edges on the path from s to the root of its tree in the proof forest
|
||||
void make_proof_root(slice s);
|
||||
// void make_proof_root(slice s);
|
||||
|
||||
/// Split slice s into s[|s|-1:cut+1] and s[cut:0]
|
||||
void split(slice s, unsigned cut);
|
||||
void split_core(slice s, unsigned cut);
|
||||
|
||||
/// Retrieve base slices s_1,...,s_n such that src == s_1 ++ ... ++ s_n
|
||||
void find_base(slice src, slice_vector& out_base) const;
|
||||
/// Retrieve (or create) base slices s_1,...,s_n such that src[hi:lo] == s_1 ++ ... ++ s_n.
|
||||
|
@ -146,11 +165,6 @@ namespace polysat {
|
|||
/// If output_base is false, return coarsest intermediate slices instead of only base slices.
|
||||
void mk_slice(slice src, unsigned hi, unsigned lo, slice_vector& out, bool output_full_src = false, bool output_base = true);
|
||||
|
||||
/// Upper subslice (direct child, not necessarily the representative)
|
||||
slice sub_hi(slice s) const;
|
||||
/// Lower subslice (direct child, not necessarily the representative)
|
||||
slice sub_lo(slice s) const;
|
||||
|
||||
/// Find representative
|
||||
slice find(slice s) const;
|
||||
/// Find representative of upper subslice
|
||||
|
@ -194,20 +208,18 @@ namespace polysat {
|
|||
enum class trail_item {
|
||||
add_var,
|
||||
alloc_slice,
|
||||
split_slice,
|
||||
split_core,
|
||||
merge_base,
|
||||
mk_value_slice,
|
||||
};
|
||||
svector<trail_item> m_trail;
|
||||
slice_vector m_split_trail;
|
||||
svector<std::pair<slice, slice>> m_merge_trail; // pair of (representative, element)
|
||||
vector<val2slice_key> m_val2slice_trail;
|
||||
unsigned_vector m_scopes;
|
||||
|
||||
void undo_add_var();
|
||||
void undo_alloc_slice();
|
||||
void undo_split_slice();
|
||||
void undo_merge_base();
|
||||
void undo_split_core();
|
||||
void undo_mk_value_slice();
|
||||
|
||||
mutable slice_vector m_tmp1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue