mirror of
https://github.com/Z3Prover/z3
synced 2026-03-17 18:43:45 +00:00
Convert dep_source to std::variant<dep_eq, dep_mem>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
af3729ef31
commit
7d78a19f1c
5 changed files with 46 additions and 47 deletions
|
|
@ -548,7 +548,7 @@ namespace seq {
|
|||
void nielsen_graph::add_str_eq(euf::snode* lhs, euf::snode* rhs) {
|
||||
if (!m_root)
|
||||
m_root = mk_node();
|
||||
dep_tracker dep = m_dep_mgr.mk_leaf({dep_source::kind::eq, m_num_input_eqs});
|
||||
dep_tracker dep = m_dep_mgr.mk_leaf(dep_eq{m_num_input_eqs});
|
||||
str_eq eq(lhs, rhs, dep);
|
||||
eq.sort();
|
||||
m_root->add_str_eq(eq);
|
||||
|
|
@ -558,7 +558,7 @@ namespace seq {
|
|||
void nielsen_graph::add_str_mem(euf::snode* str, euf::snode* regex) {
|
||||
if (!m_root)
|
||||
m_root = mk_node();
|
||||
dep_tracker dep = m_dep_mgr.mk_leaf({dep_source::kind::mem, m_num_input_mems});
|
||||
dep_tracker dep = m_dep_mgr.mk_leaf(dep_mem{m_num_input_mems});
|
||||
euf::snode* history = m_sg.mk_empty_seq(str->get_sort());
|
||||
unsigned id = next_mem_id();
|
||||
m_root->add_str_mem(str_mem(str, regex, history, id, dep));
|
||||
|
|
@ -3941,10 +3941,10 @@ namespace seq {
|
|||
vector<dep_source, false> vs;
|
||||
m_dep_mgr.linearize(deps, vs);
|
||||
for (dep_source const& d : vs) {
|
||||
if (d.m_kind == dep_source::kind::eq)
|
||||
eq_indices.push_back(d.index);
|
||||
if (std::holds_alternative<dep_eq>(d))
|
||||
eq_indices.push_back(std::get<dep_eq>(d).index);
|
||||
else
|
||||
mem_indices.push_back(d.index);
|
||||
mem_indices.push_back(std::get<dep_mem>(d).index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ Author:
|
|||
#include "ast/euf/euf_sgraph.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include "model/model.h"
|
||||
|
||||
namespace seq {
|
||||
|
|
@ -303,15 +304,11 @@ namespace seq {
|
|||
};
|
||||
|
||||
// source of a dependency: identifies an input constraint by kind and index.
|
||||
// kind::eq means a string equality, kind::mem means a regex membership.
|
||||
// dep_eq means a string equality, dep_mem means a regex membership.
|
||||
// index is the 0-based position in the input eq or mem list respectively.
|
||||
struct dep_source {
|
||||
enum class kind { eq, mem } m_kind;
|
||||
unsigned index;
|
||||
bool operator==(dep_source const& o) const {
|
||||
return m_kind == o.m_kind && index == o.index;
|
||||
}
|
||||
};
|
||||
struct dep_eq { unsigned index; bool operator==(dep_eq const& o) const { return index == o.index; } };
|
||||
struct dep_mem { unsigned index; bool operator==(dep_mem const& o) const { return index == o.index; } };
|
||||
using dep_source = std::variant<dep_eq, dep_mem>;
|
||||
|
||||
// Arena-based dependency manager: builds an immutable tree of dep_source
|
||||
// leaves joined by binary join nodes. Memory is managed via a region;
|
||||
|
|
|
|||
|
|
@ -456,14 +456,15 @@ namespace smt {
|
|||
vector<seq::dep_source, false> vs;
|
||||
m_nielsen.dep_mgr().linearize(deps, vs);
|
||||
for (seq::dep_source const& d : vs) {
|
||||
if (d.m_kind == seq::dep_source::kind::eq) {
|
||||
eq_source const& src = m_state.get_eq_source(d.index);
|
||||
if (std::holds_alternative<seq::dep_eq>(d)) {
|
||||
eq_source const& src = m_state.get_eq_source(std::get<seq::dep_eq>(d).index);
|
||||
if (src.m_n1->get_root() == src.m_n2->get_root())
|
||||
eqs.push_back({src.m_n1, src.m_n2});
|
||||
}
|
||||
else {
|
||||
if (d.index < m_nielsen_to_state_mem.size()) {
|
||||
unsigned state_mem_idx = m_nielsen_to_state_mem[d.index];
|
||||
unsigned idx = std::get<seq::dep_mem>(d).index;
|
||||
if (idx < m_nielsen_to_state_mem.size()) {
|
||||
unsigned state_mem_idx = m_nielsen_to_state_mem[idx];
|
||||
mem_source const& src = m_state.get_mem_source(state_mem_idx);
|
||||
SASSERT(ctx.get_assignment(src.m_lit) == l_true);
|
||||
lits.push_back(src.m_lit);
|
||||
|
|
|
|||
|
|
@ -45,24 +45,24 @@ static void test_dep_tracker() {
|
|||
SASSERT(d0 == nullptr);
|
||||
|
||||
// tracker with one leaf
|
||||
seq::dep_tracker d1 = dm.mk_leaf({seq::dep_source::kind::eq, 3});
|
||||
seq::dep_tracker d1 = dm.mk_leaf(seq::dep_eq{3});
|
||||
SASSERT(d1 != nullptr);
|
||||
|
||||
// tracker with another leaf
|
||||
seq::dep_tracker d2 = dm.mk_leaf({seq::dep_source::kind::mem, 5});
|
||||
seq::dep_tracker d2 = dm.mk_leaf(seq::dep_mem{5});
|
||||
SASSERT(d2 != nullptr);
|
||||
|
||||
// merge
|
||||
seq::dep_tracker d3 = dm.mk_join(d1, d2);
|
||||
SASSERT(d3 != nullptr);
|
||||
SASSERT(dm.contains(d3, {seq::dep_source::kind::eq, 3}));
|
||||
SASSERT(dm.contains(d3, {seq::dep_source::kind::mem, 5}));
|
||||
SASSERT(!dm.contains(d1, {seq::dep_source::kind::mem, 5}));
|
||||
SASSERT(dm.contains(d3, seq::dep_eq{3}));
|
||||
SASSERT(dm.contains(d3, seq::dep_mem{5}));
|
||||
SASSERT(!dm.contains(d1, seq::dep_mem{5}));
|
||||
|
||||
// another leaf with same value as d1
|
||||
seq::dep_tracker d4 = dm.mk_leaf({seq::dep_source::kind::eq, 3});
|
||||
SASSERT(dm.contains(d4, {seq::dep_source::kind::eq, 3}));
|
||||
SASSERT(!dm.contains(d4, {seq::dep_source::kind::mem, 5}));
|
||||
seq::dep_tracker d4 = dm.mk_leaf(seq::dep_eq{3});
|
||||
SASSERT(dm.contains(d4, seq::dep_eq{3}));
|
||||
SASSERT(!dm.contains(d4, seq::dep_mem{5}));
|
||||
}
|
||||
|
||||
// test str_eq constraint creation and operations
|
||||
|
|
@ -1431,39 +1431,40 @@ static void test_dep_tracker_get_set_bits() {
|
|||
SASSERT(bits0.empty());
|
||||
|
||||
// single leaf at eq-index 5
|
||||
seq::dep_tracker d1 = dm.mk_leaf({seq::dep_source::kind::eq, 5});
|
||||
seq::dep_tracker d1 = dm.mk_leaf(seq::dep_eq{5});
|
||||
vector<seq::dep_source, false> bits1;
|
||||
dm.linearize(d1, bits1);
|
||||
SASSERT(bits1.size() == 1);
|
||||
SASSERT(bits1[0].index == 5);
|
||||
SASSERT(bits1[0].m_kind == seq::dep_source::kind::eq);
|
||||
SASSERT(std::get<seq::dep_eq>(bits1[0]).index == 5);
|
||||
SASSERT(std::holds_alternative<seq::dep_eq>(bits1[0]));
|
||||
|
||||
// two leaves merged: eq-index 3 and mem-index 11
|
||||
seq::dep_tracker d2 = dm.mk_join(
|
||||
dm.mk_leaf({seq::dep_source::kind::eq, 3}),
|
||||
dm.mk_leaf({seq::dep_source::kind::mem, 11}));
|
||||
dm.mk_leaf(seq::dep_eq{3}),
|
||||
dm.mk_leaf(seq::dep_mem{11}));
|
||||
vector<seq::dep_source, false> bits2;
|
||||
dm.linearize(d2, bits2);
|
||||
SASSERT(bits2.size() == 2);
|
||||
bool has_eq3 = false, has_mem11 = false;
|
||||
for (auto const& d : bits2) {
|
||||
if (d.m_kind == seq::dep_source::kind::eq && d.index == 3) has_eq3 = true;
|
||||
if (d.m_kind == seq::dep_source::kind::mem && d.index == 11) has_mem11 = true;
|
||||
if (std::holds_alternative<seq::dep_eq>(d) && std::get<seq::dep_eq>(d).index == 3) has_eq3 = true;
|
||||
if (std::holds_alternative<seq::dep_mem>(d) && std::get<seq::dep_mem>(d).index == 11) has_mem11 = true;
|
||||
}
|
||||
SASSERT(has_eq3);
|
||||
SASSERT(has_mem11);
|
||||
|
||||
// join with additional leaf
|
||||
seq::dep_tracker d3 = dm.mk_join(
|
||||
dm.mk_leaf({seq::dep_source::kind::eq, 31}),
|
||||
dm.mk_leaf({seq::dep_source::kind::mem, 32}));
|
||||
dm.mk_leaf(seq::dep_eq{31}),
|
||||
dm.mk_leaf(seq::dep_mem{32}));
|
||||
vector<seq::dep_source, false> bits3;
|
||||
dm.linearize(d3, bits3);
|
||||
SASSERT(bits3.size() == 2);
|
||||
bool has31 = false, has32 = false;
|
||||
for (auto const& d : bits3) {
|
||||
if (d.index == 31) has31 = true;
|
||||
if (d.index == 32) has32 = true;
|
||||
unsigned idx = std::visit([](auto const& s) { return s.index; }, d);
|
||||
if (idx == 31) has31 = true;
|
||||
if (idx == 32) has32 = true;
|
||||
}
|
||||
SASSERT(has31);
|
||||
SASSERT(has32);
|
||||
|
|
@ -2421,7 +2422,7 @@ static void test_length_constraints_deps() {
|
|||
ng.dep_mgr().linearize(c.m_dep, vs);
|
||||
bool found = false;
|
||||
for (auto const& d : vs)
|
||||
if (d.m_kind == seq::dep_source::kind::eq && d.index == 0) found = true;
|
||||
if (std::holds_alternative<seq::dep_eq>(d) && std::get<seq::dep_eq>(d).index == 0) found = true;
|
||||
SASSERT(found);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ static void test_generate_constraints_ab_star() {
|
|||
expr_ref re = mk_ab_star(m, seq);
|
||||
euf::snode* regex = sg.mk(re);
|
||||
seq::dep_manager dm;
|
||||
seq::dep_tracker dep = dm.mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = dm.mk_leaf(seq::dep_mem{0});
|
||||
seq::str_mem mem(x, regex, nullptr, 0, dep);
|
||||
|
||||
vector<seq::int_constraint> out;
|
||||
|
|
@ -366,7 +366,7 @@ static void test_generate_constraints_bounded_loop() {
|
|||
expr_ref re(seq.re.mk_loop(ab, 1, 3), m);
|
||||
euf::snode* regex = sg.mk(re);
|
||||
seq::dep_manager dm;
|
||||
seq::dep_tracker dep = dm.mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = dm.mk_leaf(seq::dep_mem{0});
|
||||
seq::str_mem mem(x, regex, nullptr, 0, dep);
|
||||
|
||||
vector<seq::int_constraint> out;
|
||||
|
|
@ -403,7 +403,7 @@ static void test_generate_constraints_stride_one() {
|
|||
expr_ref re(seq.re.mk_full_seq(str_sort), m);
|
||||
euf::snode* regex = sg.mk(re);
|
||||
seq::dep_manager dm;
|
||||
seq::dep_tracker dep = dm.mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = dm.mk_leaf(seq::dep_mem{0});
|
||||
seq::str_mem mem(x, regex, nullptr, 0, dep);
|
||||
|
||||
vector<seq::int_constraint> out;
|
||||
|
|
@ -426,7 +426,7 @@ static void test_generate_constraints_fixed_length() {
|
|||
expr_ref re = mk_to_re_ab(m, seq); // fixed len 2
|
||||
euf::snode* regex = sg.mk(re);
|
||||
seq::dep_manager dm;
|
||||
seq::dep_tracker dep = dm.mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = dm.mk_leaf(seq::dep_mem{0});
|
||||
seq::str_mem mem(x, regex, nullptr, 0, dep);
|
||||
|
||||
vector<seq::int_constraint> out;
|
||||
|
|
@ -449,7 +449,7 @@ static void test_generate_constraints_dep_propagated() {
|
|||
expr_ref re = mk_ab_star(m, seq);
|
||||
euf::snode* regex = sg.mk(re);
|
||||
seq::dep_manager dm;
|
||||
seq::dep_tracker dep = dm.mk_leaf({seq::dep_source::kind::mem, 7});
|
||||
seq::dep_tracker dep = dm.mk_leaf(seq::dep_mem{7});
|
||||
seq::str_mem mem(x, regex, nullptr, 0, dep);
|
||||
|
||||
vector<seq::int_constraint> out;
|
||||
|
|
@ -462,7 +462,7 @@ static void test_generate_constraints_dep_propagated() {
|
|||
dm.linearize(ic.m_dep, vs);
|
||||
bool found = false;
|
||||
for (auto const& d : vs)
|
||||
if (d.m_kind == seq::dep_source::kind::mem && d.index == 7) found = true;
|
||||
if (std::holds_alternative<seq::dep_mem>(d) && std::get<seq::dep_mem>(d).index == 7) found = true;
|
||||
SASSERT(found);
|
||||
}
|
||||
std::cout << " all constraints carry dep {mem,7}\n";
|
||||
|
|
@ -574,7 +574,7 @@ static void test_check_conflict_valid_k_exists() {
|
|||
ng.add_str_mem(x, regex);
|
||||
|
||||
// lb=3, ub=5: length 4 is achievable (k=2) → no conflict
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf(seq::dep_mem{0});
|
||||
ng.root()->add_lower_int_bound(x, 3, dep);
|
||||
ng.root()->add_upper_int_bound(x, 5, dep);
|
||||
|
||||
|
|
@ -602,7 +602,7 @@ static void test_check_conflict_no_valid_k() {
|
|||
ng.add_str_mem(x, regex);
|
||||
|
||||
// lb=3, ub=3: only odd length 3 — never a multiple of 2 → conflict
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf(seq::dep_mem{0});
|
||||
ng.root()->add_lower_int_bound(x, 3, dep);
|
||||
ng.root()->add_upper_int_bound(x, 3, dep);
|
||||
|
||||
|
|
@ -630,7 +630,7 @@ static void test_check_conflict_abc_star() {
|
|||
ng.add_str_mem(x, regex);
|
||||
|
||||
// lb=5, ub=5 → no valid k (5 is not a multiple of 3) → conflict
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf(seq::dep_mem{0});
|
||||
ng.root()->add_lower_int_bound(x, 5, dep);
|
||||
ng.root()->add_upper_int_bound(x, 5, dep);
|
||||
|
||||
|
|
@ -657,7 +657,7 @@ static void test_check_conflict_stride_one_never_conflicts() {
|
|||
euf::snode* regex = sg.mk(re);
|
||||
ng.add_str_mem(x, regex);
|
||||
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf({seq::dep_source::kind::mem, 0});
|
||||
seq::dep_tracker dep = ng.dep_mgr().mk_leaf(seq::dep_mem{0});
|
||||
ng.root()->add_lower_int_bound(x, 7, dep);
|
||||
ng.root()->add_upper_int_bound(x, 7, dep);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue