3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-04-22 11:53:29 +00:00

Add SASSERT invariants and pre/postconditions to Nielsen seq solver

Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/24442582-8437-45ae-a58f-957ac2bdf698

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-03 02:11:02 +00:00 committed by GitHub
parent 4a5ef833f2
commit 0726edcd0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 3 deletions

View file

@ -127,6 +127,7 @@ namespace seq {
if (m_lhs && m_rhs && m_lhs->id() > m_rhs->id()) { if (m_lhs && m_rhs && m_lhs->id() > m_rhs->id()) {
std::swap(m_lhs, m_rhs); std::swap(m_lhs, m_rhs);
} }
SASSERT(!m_lhs || !m_rhs || m_lhs->id() <= m_rhs->id());
} }
bool str_eq::is_trivial() const { bool str_eq::is_trivial() const {
@ -235,6 +236,10 @@ namespace seq {
// clone regex occurrence tracking // clone regex occurrence tracking
m_regex_occurrence = parent.m_regex_occurrence; m_regex_occurrence = parent.m_regex_occurrence;
SASSERT(m_str_eq.size() == parent.m_str_eq.size());
SASSERT(m_str_mem.size() == parent.m_str_mem.size());
SASSERT(m_constraints.size() == parent.m_constraints.size());
} }
bool nielsen_node::track_regex_occurrence(unsigned regex_id, unsigned mem_id) { bool nielsen_node::track_regex_occurrence(unsigned regex_id, unsigned mem_id) {
@ -269,6 +274,7 @@ namespace seq {
void nielsen_node::apply_subst(euf::sgraph& sg, nielsen_subst const& s) { void nielsen_node::apply_subst(euf::sgraph& sg, nielsen_subst const& s) {
SASSERT(s.m_var); SASSERT(s.m_var);
SASSERT(s.m_replacement != nullptr);
for (auto &eq : m_str_eq) { for (auto &eq : m_str_eq) {
auto new_lhs = sg.subst(eq.m_lhs, s.m_var, s.m_replacement); auto new_lhs = sg.subst(eq.m_lhs, s.m_var, s.m_replacement);
auto new_rhs = sg.subst(eq.m_rhs, s.m_var, s.m_replacement); auto new_rhs = sg.subst(eq.m_rhs, s.m_var, s.m_replacement);
@ -422,6 +428,7 @@ namespace seq {
unsigned id = m_nodes.size(); unsigned id = m_nodes.size();
nielsen_node* n = alloc(nielsen_node, *this, id); nielsen_node* n = alloc(nielsen_node, *this, id);
m_nodes.push_back(n); m_nodes.push_back(n);
SASSERT(n->id() == m_nodes.size() - 1);
return n; return n;
} }
@ -433,6 +440,8 @@ namespace seq {
} }
nielsen_edge* nielsen_graph::mk_edge(nielsen_node* src, nielsen_node* tgt, bool is_progress) { nielsen_edge* nielsen_graph::mk_edge(nielsen_node* src, nielsen_node* tgt, bool is_progress) {
SASSERT(src != nullptr);
SASSERT(tgt != nullptr);
nielsen_edge* e = alloc(nielsen_edge, src, tgt, is_progress); nielsen_edge* e = alloc(nielsen_edge, src, tgt, is_progress);
m_edges.push_back(e); m_edges.push_back(e);
src->add_outgoing(e); src->add_outgoing(e);
@ -505,6 +514,10 @@ namespace seq {
m_dep_mgr.reset(); m_dep_mgr.reset();
m_solver.reset(); m_solver.reset();
m_core_solver.reset(); m_core_solver.reset();
SASSERT(m_nodes.empty());
SASSERT(m_edges.empty());
SASSERT(m_root == nullptr);
SASSERT(m_sat_node == nullptr);
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -1193,8 +1206,10 @@ namespace seq {
} }
if (is_satisfied()) if (is_satisfied()) {
SASSERT(m_str_eq.empty());
return simplify_result::satisfied; return simplify_result::satisfied;
}
return simplify_result::proceed; return simplify_result::proceed;
} }
@ -1306,6 +1321,7 @@ namespace seq {
verbose_stream() << " side constraint: " << c.fml << "\n"; verbose_stream() << " side constraint: " << c.fml << "\n";
}); });
++m_stats.m_num_sat; ++m_stats.m_num_sat;
SASSERT(m_sat_node != nullptr);
return r; return r;
} }
if (r == search_result::unsat) { if (r == search_result::unsat) {
@ -2184,6 +2200,8 @@ namespace seq {
} }
bool nielsen_graph::generate_extensions(nielsen_node *node) { bool nielsen_graph::generate_extensions(nielsen_node *node) {
SASSERT(node != nullptr);
SASSERT(!node->is_currently_conflict());
// The first modifier that produces edges is used and returned immediately. // The first modifier that produces edges is used and returned immediately.
// Priority 1: deterministic modifiers (single child, always progress) // Priority 1: deterministic modifiers (single child, always progress)

View file

@ -586,8 +586,16 @@ namespace seq {
vector<str_mem> const& str_mems() const { return m_str_mem; } vector<str_mem> const& str_mems() const { return m_str_mem; }
vector<str_mem>& str_mems() { return m_str_mem; } vector<str_mem>& str_mems() { return m_str_mem; }
void add_str_eq(str_eq const& eq) { m_str_eq.push_back(eq); } void add_str_eq(str_eq const& eq) {
void add_str_mem(str_mem const& mem) { m_str_mem.push_back(mem); } SASSERT(eq.m_lhs != nullptr);
SASSERT(eq.m_rhs != nullptr);
m_str_eq.push_back(eq);
}
void add_str_mem(str_mem const& mem) {
SASSERT(mem.m_str != nullptr);
SASSERT(mem.m_regex != nullptr);
m_str_mem.push_back(mem);
}
bool add_constraint(constraint const &ic); bool add_constraint(constraint const &ic);
vector<constraint> const& constraints() const { return m_constraints; } vector<constraint> const& constraints() const { return m_constraints; }
@ -857,6 +865,9 @@ namespace seq {
void create_root() { void create_root() {
SASSERT(!root()); SASSERT(!root());
set_root(mk_node()); set_root(mk_node());
SASSERT(m_root != nullptr);
SASSERT(m_root->id() == 0);
SASSERT(m_nodes[0] == m_root);
} }
// path of edges from root to sat_node (set when sat_node is set) // path of edges from root to sat_node (set when sat_node is set)