mirror of
https://github.com/Z3Prover/z3
synced 2026-06-20 15:40:37 +00:00
euf_sgraph: make drop_left/drop_right depth-linear and simplify string classification (#9771)
ZIPT review identified two hot-path inefficiencies in `euf_sgraph`:
`drop_left`/`drop_right` were implemented as repeated single-token drops
(`O(count × depth)`), and `classify` performed redundant string checks.
This change aligns behavior with the intended tree-navigation approach
while keeping semantics unchanged.
- **Algorithmic update: `drop_left` / `drop_right`**
- Replaced iterative `drop_first`/`drop_last` loops with direct
recursion over concat children.
- New logic drops across subtree boundaries using child lengths,
reducing work to tree depth (`O(depth)`).
- **Classification cleanup: `classify`**
- Collapsed double `is_string` probing into a single `is_string(e, s)`
call.
- Preserves existing kind mapping (`empty` vs non-empty string constant
handling).
- **Focused test coverage extension**
- Added boundary checks in `test_sgraph_drop` for `drop_left(..., 1)`
and `drop_right(..., 1)` on a 4-token concat tree.
```cpp
snode* sgraph::drop_left(snode* n, unsigned count) {
if (count == 0 || n->is_empty()) return n;
if (count >= n->length()) return mk_empty_seq(n->get_sort());
SASSERT(n->is_concat());
unsigned left_len = n->arg(0)->length();
if (count < left_len)
return mk_concat(drop_left(n->arg(0), count), n->arg(1));
return drop_left(n->arg(1), count - left_len);
}
```
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
parent
294ee984b8
commit
03a76c0309
2 changed files with 26 additions and 11 deletions
|
|
@ -564,11 +564,23 @@ static void test_sgraph_drop() {
|
|||
SASSERT(cd2->length() == 2);
|
||||
SASSERT(cd2->first() == c);
|
||||
|
||||
// drop_left(1): [A, B, C, D] => [B, C, D]
|
||||
euf::snode* bcd2 = sg.drop_left(abcd, 1);
|
||||
SASSERT(bcd2->length() == 3);
|
||||
SASSERT(bcd2->first() == b);
|
||||
SASSERT(bcd2->last() == d);
|
||||
|
||||
// drop_right(2): [A, B, C, D] => [A, B]
|
||||
euf::snode* ab2 = sg.drop_right(abcd, 2);
|
||||
SASSERT(ab2->length() == 2);
|
||||
SASSERT(ab2->last() == b);
|
||||
|
||||
// drop_right(1): [A, B, C, D] => [A, B, C]
|
||||
euf::snode* abc2 = sg.drop_right(abcd, 1);
|
||||
SASSERT(abc2->length() == 3);
|
||||
SASSERT(abc2->first() == a);
|
||||
SASSERT(abc2->last() == c);
|
||||
|
||||
// drop all: [A, B, C, D] => empty
|
||||
euf::snode* empty = sg.drop_left(abcd, 4);
|
||||
SASSERT(empty->is_empty());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue