3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-05-17 07:29:28 +00:00

Refactor: replace int_constraint with constraint struct, promote cur_path to member, expose path leaf side constraints (#9124)

* chore: update plan with cur_path and side constraints requirements

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/1523cf0a-b7a4-41a6-b792-7cd41b4dcd3b

* Refactor: rename int_constraint to constraint, remove int_constraint_kind enum

- Rename int_constraint struct to constraint with fields fml/dep
- Remove int_constraint_kind enum; pre-build formula expressions instead
- nielsen_edge: add_side_int/side_int() -> add_side_constraint/side_constraints()
- nielsen_node: add_int_constraint/int_constraints() -> add_constraint/constraints()
- nielsen_graph: mk_int_constraint(lhs,rhs,kind,dep) -> mk_constraint(fml,dep)
- Remove int_constraint_to_expr (no longer needed)
- search_dfs/simplify_and_init/check_int_feasibility/check_lp_le: drop cur_path param
- Add m_cur_path member to nielsen_graph; m_cur_path.reset() in solve()
- Add get_path_leaf_side_constraints() implementation
- Update seq_parikh.h/cpp and seq_nielsen_pp.cpp to use new constraint API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: constraint struct, promote cur_path, expose path leaf side constraints

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/1523cf0a-b7a4-41a6-b792-7cd41b4dcd3b

* fix: remove spurious includes from seq_nielsen.cpp

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/aa283d79-cd42-4b87-aaf0-4273a8327b76

* fix: update test files to use renamed constraint API and fix inverted root guard

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/b09bbc56-9617-4277-8e0c-27fa7e588037

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Copilot 2026-03-24 22:18:30 -07:00 committed by GitHub
parent 9f6eb4f455
commit e3e235aa7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 183 additions and 231 deletions

View file

@ -326,7 +326,7 @@ static void test_generate_constraints_ab_star() {
seq::dep_tracker dep = dm.mk_leaf(lit);
seq::str_mem mem(x, regex, nullptr, 0, dep);
vector<seq::int_constraint> out;
vector<seq::constraint> out;
parikh.generate_parikh_constraints(mem, out);
// expect at least: len(x)=0+2k and k>=0
@ -337,19 +337,19 @@ static void test_generate_constraints_ab_star() {
// check that one constraint is an equality (len(x) = 0 + 2·k)
bool has_eq = false;
for (auto const& ic : out)
if (ic.m_kind == seq::int_constraint_kind::eq) has_eq = true;
if (m.is_eq(ic.fml)) has_eq = true;
SASSERT(has_eq);
// check that one constraint is k >= 0
bool has_ge = false;
for (auto const& ic : out)
if (ic.m_kind == seq::int_constraint_kind::ge) has_ge = true;
if (arith.is_ge(ic.fml)) has_ge = true;
SASSERT(has_ge);
// should NOT have an upper bound (star is unbounded)
bool has_le = false;
for (auto const& ic : out)
if (ic.m_kind == seq::int_constraint_kind::le) has_le = true;
if (arith.is_le(ic.fml)) has_le = true;
SASSERT(!has_le);
}
@ -361,6 +361,7 @@ static void test_generate_constraints_bounded_loop() {
euf::egraph eg(m);
euf::sgraph sg(m, eg);
seq_util seq(m);
arith_util arith(m);
seq::seq_parikh parikh(sg);
euf::snode* x = sg.mk_var(symbol("x"), sg.get_str_sort());
@ -372,7 +373,7 @@ static void test_generate_constraints_bounded_loop() {
seq::dep_tracker dep = dm.mk_leaf(sat::null_literal);
seq::str_mem mem(x, regex, nullptr, 0, dep);
vector<seq::int_constraint> out;
vector<seq::constraint> out;
parikh.generate_parikh_constraints(mem, out);
// expect: eq + ge + le = 3 constraints
@ -381,9 +382,9 @@ static void test_generate_constraints_bounded_loop() {
bool has_eq = false, has_ge = false, has_le = false;
for (auto const& ic : out) {
if (ic.m_kind == seq::int_constraint_kind::eq) has_eq = true;
if (ic.m_kind == seq::int_constraint_kind::ge) has_ge = true;
if (ic.m_kind == seq::int_constraint_kind::le) has_le = true;
if (m.is_eq(ic.fml)) has_eq = true;
if (arith.is_ge(ic.fml)) has_ge = true;
if (arith.is_le(ic.fml)) has_le = true;
}
SASSERT(has_eq);
SASSERT(has_ge);
@ -409,7 +410,7 @@ static void test_generate_constraints_stride_one() {
seq::dep_tracker dep = dm.mk_leaf(sat::null_literal);
seq::str_mem mem(x, regex, nullptr, 0, dep);
vector<seq::int_constraint> out;
vector<seq::constraint> out;
parikh.generate_parikh_constraints(mem, out);
std::cout << " generated " << out.size() << " constraints (expect 0)\n";
SASSERT(out.empty());
@ -432,7 +433,7 @@ static void test_generate_constraints_fixed_length() {
seq::dep_tracker dep = dm.mk_leaf(sat::null_literal);
seq::str_mem mem(x, regex, nullptr, 0, dep);
vector<seq::int_constraint> out;
vector<seq::constraint> out;
parikh.generate_parikh_constraints(mem, out);
std::cout << " generated " << out.size() << " constraints (expect 0)\n";
SASSERT(out.empty());
@ -456,14 +457,14 @@ static void test_generate_constraints_dep_propagated() {
seq::dep_tracker dep = dm.mk_leaf(lit);
seq::str_mem mem(x, regex, nullptr, 0, dep);
vector<seq::int_constraint> out;
vector<seq::constraint> out;
parikh.generate_parikh_constraints(mem, out);
// all generated constraints must carry dep_source{mem,7} in their dependency
for (auto const& ic : out) {
SASSERT(ic.m_dep != nullptr);
SASSERT(ic.dep != nullptr);
vector<seq::dep_source, false> vs;
dm.linearize(ic.m_dep, vs);
dm.linearize(ic.dep, vs);
bool found = false;
for (auto const& d : vs)
if (std::get<sat::literal>(d) == lit) found = true;
@ -495,11 +496,11 @@ static void test_apply_to_node_adds_constraints() {
// root node should have no int_constraints initially
SASSERT(ng.root() != nullptr);
unsigned before = ng.root()->int_constraints().size();
unsigned before = ng.root()->constraints().size();
parikh.apply_to_node(*ng.root());
unsigned after = ng.root()->int_constraints().size();
unsigned after = ng.root()->constraints().size();
std::cout << " before=" << before << " after=" << after << "\n";
SASSERT(after > before);
}
@ -525,9 +526,9 @@ static void test_apply_to_node_stride_one_no_constraints() {
euf::snode* regex = sg.mk(re);
ng.add_str_mem(x, regex);
unsigned before = ng.root()->int_constraints().size();
unsigned before = ng.root()->constraints().size();
parikh.apply_to_node(*ng.root());
unsigned after = ng.root()->int_constraints().size();
unsigned after = ng.root()->constraints().size();
std::cout << " before=" << before << " after=" << after << " (expect no change)\n";
SASSERT(after == before);
}