mirror of
https://github.com/Z3Prover/z3
synced 2026-06-12 03:45:38 +00:00
We don't need to handle negative membership constraints explicitly
This commit is contained in:
parent
4e7d83f996
commit
b2838b472d
7 changed files with 121 additions and 117 deletions
|
|
@ -260,6 +260,8 @@ namespace seq {
|
|||
m_nodes.reset();
|
||||
m_edges.reset();
|
||||
m_root = nullptr;
|
||||
m_sat_node = nullptr;
|
||||
m_sat_path.reset();
|
||||
m_run_idx = 0;
|
||||
m_depth_bound = 0;
|
||||
m_next_mem_id = 0;
|
||||
|
|
@ -533,6 +535,8 @@ namespace seq {
|
|||
return search_result::sat;
|
||||
|
||||
++m_stats.m_num_solve_calls;
|
||||
m_sat_node = nullptr;
|
||||
m_sat_path.reset();
|
||||
|
||||
// Iterative deepening: start at depth 3, increment by 1 on each failure.
|
||||
// m_max_search_depth == 0 means unlimited; otherwise stop when bound exceeds it.
|
||||
|
|
@ -541,7 +545,8 @@ namespace seq {
|
|||
if (m_max_search_depth > 0 && m_depth_bound > m_max_search_depth)
|
||||
break;
|
||||
inc_run_idx();
|
||||
search_result r = search_dfs(m_root, 0);
|
||||
svector<nielsen_edge*> cur_path;
|
||||
search_result r = search_dfs(m_root, 0, cur_path);
|
||||
if (r == search_result::sat) {
|
||||
++m_stats.m_num_sat;
|
||||
return r;
|
||||
|
|
@ -559,7 +564,7 @@ namespace seq {
|
|||
return search_result::unknown;
|
||||
}
|
||||
|
||||
nielsen_graph::search_result nielsen_graph::search_dfs(nielsen_node* node, unsigned depth) {
|
||||
nielsen_graph::search_result nielsen_graph::search_dfs(nielsen_node* node, unsigned depth, svector<nielsen_edge*>& cur_path) {
|
||||
++m_stats.m_num_dfs_nodes;
|
||||
if (depth > m_stats.m_max_depth)
|
||||
m_stats.m_max_depth = depth;
|
||||
|
|
@ -567,8 +572,11 @@ namespace seq {
|
|||
// cycle/revisit detection: if already visited this run, return cached status.
|
||||
// mirrors ZIPT's NielsenNode.GraphExpansion() evalIdx check.
|
||||
if (node->eval_idx() == m_run_idx) {
|
||||
if (node->is_satisfied())
|
||||
if (node->is_satisfied()) {
|
||||
m_sat_node = node;
|
||||
m_sat_path = cur_path;
|
||||
return search_result::sat;
|
||||
}
|
||||
if (node->is_currently_conflict())
|
||||
return search_result::unsat;
|
||||
return search_result::unknown;
|
||||
|
|
@ -583,8 +591,11 @@ namespace seq {
|
|||
node->set_general_conflict(true);
|
||||
return search_result::unsat;
|
||||
}
|
||||
if (sr == simplify_result::satisfied || node->is_satisfied())
|
||||
if (sr == simplify_result::satisfied || node->is_satisfied()) {
|
||||
m_sat_node = node;
|
||||
m_sat_path = cur_path;
|
||||
return search_result::sat;
|
||||
}
|
||||
|
||||
// depth bound check
|
||||
if (depth >= m_depth_bound)
|
||||
|
|
@ -611,10 +622,11 @@ namespace seq {
|
|||
// explore children
|
||||
bool any_unknown = false;
|
||||
for (nielsen_edge* e : node->outgoing()) {
|
||||
nielsen_node* child = e->tgt();
|
||||
search_result r = search_dfs(child, depth + 1);
|
||||
cur_path.push_back(e);
|
||||
search_result r = search_dfs(e->tgt(), depth + 1, cur_path);
|
||||
if (r == search_result::sat)
|
||||
return search_result::sat;
|
||||
cur_path.pop_back();
|
||||
if (r == search_result::unknown)
|
||||
any_unknown = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ namespace seq {
|
|||
// edges
|
||||
ptr_vector<nielsen_edge> m_outgoing;
|
||||
nielsen_node* m_backedge = nullptr;
|
||||
nielsen_edge* m_parent_edge = nullptr;
|
||||
|
||||
// status flags
|
||||
bool m_is_general_conflict = false;
|
||||
|
|
@ -457,6 +458,9 @@ namespace seq {
|
|||
nielsen_node* backedge() const { return m_backedge; }
|
||||
void set_backedge(nielsen_node* n) { m_backedge = n; }
|
||||
|
||||
nielsen_edge* parent_edge() const { return m_parent_edge; }
|
||||
void set_parent_edge(nielsen_edge* e) { m_parent_edge = e; }
|
||||
|
||||
// status
|
||||
bool is_general_conflict() const { return m_is_general_conflict; }
|
||||
void set_general_conflict(bool v) { m_is_general_conflict = v; }
|
||||
|
|
@ -532,6 +536,8 @@ namespace seq {
|
|||
ptr_vector<nielsen_node> m_nodes;
|
||||
ptr_vector<nielsen_edge> m_edges;
|
||||
nielsen_node* m_root = nullptr;
|
||||
nielsen_node* m_sat_node = nullptr;
|
||||
svector<nielsen_edge*> m_sat_path;
|
||||
unsigned m_run_idx = 0;
|
||||
unsigned m_depth_bound = 0;
|
||||
unsigned m_max_search_depth = 0;
|
||||
|
|
@ -558,6 +564,11 @@ namespace seq {
|
|||
nielsen_node* root() const { return m_root; }
|
||||
void set_root(nielsen_node* n) { m_root = n; }
|
||||
|
||||
// satisfying leaf node (set by solve() when result is sat)
|
||||
nielsen_node* sat_node() const { return m_sat_node; }
|
||||
// path of edges from root to sat_node (set when sat_node is set)
|
||||
svector<nielsen_edge*> const& sat_path() const { return m_sat_path; }
|
||||
|
||||
// add constraints to the root node from external solver
|
||||
void add_str_eq(euf::snode* lhs, euf::snode* rhs);
|
||||
void add_str_mem(euf::snode* str, euf::snode* regex);
|
||||
|
|
@ -625,7 +636,7 @@ namespace seq {
|
|||
void generate_length_constraints(vector<length_constraint>& constraints);
|
||||
|
||||
private:
|
||||
search_result search_dfs(nielsen_node* node, unsigned depth);
|
||||
search_result search_dfs(nielsen_node* node, unsigned depth, svector<nielsen_edge*>& cur_path);
|
||||
|
||||
// create a fresh variable with a unique name
|
||||
euf::snode* mk_fresh_var();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue