3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-04-14 16:25:11 +00:00

Move nseq_regex/state into smt/seq and seq_model into smt/; rename to seq_* prefix (#8984)

* Initial plan

* build verified: nseq_regex moved to smt/seq

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* rename nseq_regex/state/model to seq_regex/state/model in smt/seq; add Clemens Eisenhofer as co-author

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* seq_model: remove theory_nseq dependency; get family_id from seq_util

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Add comments for regex enhancements in seq_model

Added comments regarding future improvements for regex handling.

* Add comments for large exponent handling

Add comments for handling large exponents in seq_model.cpp

* Revise comments for clarity on sort usage

Updated comments to reflect review suggestions regarding the use of the sort of 'n'.

* seq_state: remove sgraph dep; seq_model: use snode sort for is_empty; remove NSB review comments

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Update seq_state.h

* Remove unnecessary include for smt_context.h

* move seq_model from smt/seq/ to smt/; fix seq_state.h add_str_mem typo

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

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: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Copilot 2026-03-14 11:45:32 -07:00 committed by GitHub
parent 27f5541b0b
commit 5a3dbaf9f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 172 additions and 164 deletions

View file

@ -134,7 +134,7 @@ add_executable(test-z3
seq_nielsen.cpp
seq_parikh.cpp
nseq_basic.cpp
nseq_regex.cpp
seq_regex.cpp
nseq_zipt.cpp
small_object_allocator.cpp
smt2print_parse.cpp

View file

@ -289,7 +289,7 @@ int main(int argc, char ** argv) {
TST(seq_nielsen);
TST(seq_parikh);
TST(nseq_basic);
TST(nseq_regex);
TST(seq_regex);
TST(nseq_zipt);
TST(ho_matcher);
TST(finite_set);

View file

@ -3,11 +3,11 @@ Copyright (c) 2026 Microsoft Corporation
Module Name:
nseq_regex.cpp
seq_regex.cpp
Abstract:
Unit tests for nseq_regex: lazy regex membership processing
Unit tests for seq_regex: lazy regex membership processing
for the Nielsen-based string solver.
--*/
@ -15,32 +15,32 @@ Abstract:
#include "ast/reg_decl_plugins.h"
#include "ast/euf/euf_egraph.h"
#include "ast/euf/euf_sgraph.h"
#include "smt/nseq_regex.h"
#include "smt/seq/seq_regex.h"
#include "smt/seq/seq_nielsen.h"
#include "util/lbool.h"
#include "util/zstring.h"
#include <iostream>
// Test 1: nseq_regex instantiation
static void test_nseq_regex_instantiation() {
std::cout << "test_nseq_regex_instantiation\n";
// Test 1: seq_regex instantiation
static void test_seq_regex_instantiation() {
std::cout << "test_seq_regex_instantiation\n";
ast_manager m;
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
SASSERT(&nr.sg() == &sg);
std::cout << " ok\n";
}
// Test 2: is_empty_regex on an empty-language node
static void test_nseq_regex_is_empty() {
std::cout << "test_nseq_regex_is_empty\n";
static void test_seq_regex_is_empty() {
std::cout << "test_seq_regex_is_empty\n";
ast_manager m;
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -52,13 +52,13 @@ static void test_nseq_regex_is_empty() {
}
// Test 3: is_empty_regex on a full-match regex (not empty)
static void test_nseq_regex_is_full() {
std::cout << "test_nseq_regex_is_full\n";
static void test_seq_regex_is_full() {
std::cout << "test_seq_regex_is_full\n";
ast_manager m;
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -76,7 +76,7 @@ static void test_strengthened_stabilizer_null() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
SASSERT(nr.strengthened_stabilizer(nullptr, nullptr) == nullptr);
@ -100,7 +100,7 @@ static void test_strengthened_stabilizer_single_char() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// Build a*
@ -126,7 +126,7 @@ static void test_strengthened_stabilizer_two_char() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// Build (ab)*
@ -152,7 +152,7 @@ static void test_filtered_stabilizer_star_empty() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -173,7 +173,7 @@ static void test_filtered_stabilizer_star_with_stab() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// Build a* as the regex state
@ -201,7 +201,7 @@ static void test_filtered_stabilizer_star_filtered() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// Build a* as the regex state
@ -227,7 +227,7 @@ static void test_extract_cycle_history_basic() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -265,7 +265,7 @@ static void test_extract_cycle_history_null_ancestor() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -297,7 +297,7 @@ static void test_bfs_empty_none() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
sort* re_sort = su.re.mk_re(str_sort);
@ -316,7 +316,7 @@ static void test_bfs_nonempty_full() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
sort* re_sort = su.re.mk_re(str_sort);
@ -335,7 +335,7 @@ static void test_bfs_nonempty_to_re() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
expr_ref to_re_abc(su.re.mk_to_re(su.str.mk_string("abc")), m);
@ -352,7 +352,7 @@ static void test_bfs_nonempty_star() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
expr_ref star_a(su.re.mk_star(su.re.mk_to_re(su.str.mk_string("a"))), m);
@ -369,7 +369,7 @@ static void test_bfs_empty_union_of_empties() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
sort* re_sort = su.re.mk_re(str_sort);
@ -390,7 +390,7 @@ static void test_bfs_nonempty_range() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -410,7 +410,7 @@ static void test_bfs_empty_complement_full() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
sort* re_sort = su.re.mk_re(str_sort);
@ -429,7 +429,7 @@ static void test_bfs_null_safety() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
lbool result = nr.is_empty_bfs(nullptr);
SASSERT(result == l_undef);
@ -443,7 +443,7 @@ static void test_bfs_bounded() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// (a|b)+ requires at least one char; with max_states=1 should bail
@ -495,7 +495,7 @@ static void test_stabilizer_store_basic() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
expr_ref a_re(su.re.mk_to_re(su.str.mk_string("a")), m);
@ -527,7 +527,7 @@ static void test_self_stabilizing() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
expr_ref a_re(su.re.mk_to_re(su.str.mk_string("a")), m);
@ -552,7 +552,7 @@ static void test_check_intersection_sat() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// a* ∩ (a|b)* should be non-empty (both accept "a")
@ -580,7 +580,7 @@ static void test_check_intersection_unsat() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -605,7 +605,7 @@ static void test_is_language_subset_true() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// a* ⊆ (a|b)* should be true
@ -630,7 +630,7 @@ static void test_is_language_subset_false() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
// (a|b)* ⊄ a* should be false (b ∈ (a|b)* but b ∉ a*)
@ -655,7 +655,7 @@ static void test_is_language_subset_trivial() {
reg_decl_plugins(m);
euf::egraph eg(m);
euf::sgraph sg(m, eg);
smt::nseq_regex nr(sg);
seq::seq_regex nr(sg);
seq_util su(m);
sort* str_sort = su.str.mk_string_sort();
@ -677,10 +677,10 @@ static void test_is_language_subset_trivial() {
std::cout << " ok\n";
}
void tst_nseq_regex() {
test_nseq_regex_instantiation();
test_nseq_regex_is_empty();
test_nseq_regex_is_full();
void tst_seq_regex() {
test_seq_regex_instantiation();
test_seq_regex_is_empty();
test_seq_regex_is_full();
test_strengthened_stabilizer_null();
test_strengthened_stabilizer_single_char();
test_strengthened_stabilizer_two_char();
@ -707,5 +707,5 @@ void tst_nseq_regex() {
test_is_language_subset_true();
test_is_language_subset_false();
test_is_language_subset_trivial();
std::cout << "nseq_regex: all tests passed\n";
std::cout << "seq_regex: all tests passed\n";
}