mirror of
https://github.com/Z3Prover/z3
synced 2025-07-31 08:23:17 +00:00
Implement batch initialization fix for O(n²) datatype performance issue
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
115da30317
commit
b518327650
3 changed files with 55 additions and 0 deletions
|
@ -1121,6 +1121,56 @@ namespace datatype {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void util::batch_initialize_constructor_functions(sort * datatype) {
|
||||||
|
SASSERT(is_datatype(datatype));
|
||||||
|
def const& dd = get_def(datatype);
|
||||||
|
|
||||||
|
// Get all constructors for this datatype
|
||||||
|
ptr_vector<func_decl> const* constructors = get_datatype_constructors(datatype);
|
||||||
|
if (!constructors) return;
|
||||||
|
|
||||||
|
// Process all constructors in a single pass to avoid O(n²) behavior
|
||||||
|
for (func_decl * con : *constructors) {
|
||||||
|
// Initialize recognizer if not already cached
|
||||||
|
if (!plugin().m_constructor2recognizer.contains(con)) {
|
||||||
|
symbol r;
|
||||||
|
for (constructor const* c : dd) {
|
||||||
|
if (c->name() == con->get_name()) {
|
||||||
|
r = c->recognizer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parameter ps[2] = { parameter(con), parameter(r) };
|
||||||
|
func_decl* d = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype);
|
||||||
|
plugin().add_ast(con);
|
||||||
|
plugin().add_ast(d);
|
||||||
|
plugin().m_constructor2recognizer.insert(con, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize accessors if not already cached
|
||||||
|
if (!plugin().m_constructor2accessors.contains(con)) {
|
||||||
|
ptr_vector<func_decl>* res = alloc(ptr_vector<func_decl>);
|
||||||
|
plugin().add_ast(con);
|
||||||
|
plugin().m_vectors.push_back(res);
|
||||||
|
plugin().m_constructor2accessors.insert(con, res);
|
||||||
|
|
||||||
|
if (con->get_arity() > 0) {
|
||||||
|
// Find the constructor definition and create accessors
|
||||||
|
for (constructor const* c : dd) {
|
||||||
|
if (c->name() == con->get_name()) {
|
||||||
|
for (accessor const* a : *c) {
|
||||||
|
func_decl_ref fn = a->instantiate(datatype);
|
||||||
|
res->push_back(fn);
|
||||||
|
plugin().add_ast(fn);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app* util::mk_is(func_decl * c, expr *f) {
|
app* util::mk_is(func_decl * c, expr *f) {
|
||||||
return m.mk_app(get_constructor_is(c), f);
|
return m.mk_app(get_constructor_is(c), f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,6 +373,7 @@ namespace datatype {
|
||||||
func_decl * get_constructor_recognizer(func_decl * constructor);
|
func_decl * get_constructor_recognizer(func_decl * constructor);
|
||||||
func_decl * get_constructor_is(func_decl * constructor);
|
func_decl * get_constructor_is(func_decl * constructor);
|
||||||
ptr_vector<func_decl> const * get_constructor_accessors(func_decl * constructor);
|
ptr_vector<func_decl> const * get_constructor_accessors(func_decl * constructor);
|
||||||
|
void batch_initialize_constructor_functions(sort * datatype);
|
||||||
func_decl * get_accessor_constructor(func_decl * accessor);
|
func_decl * get_accessor_constructor(func_decl * accessor);
|
||||||
func_decl * get_recognizer_constructor(func_decl * recognizer) const;
|
func_decl * get_recognizer_constructor(func_decl * recognizer) const;
|
||||||
func_decl * get_update_accessor(func_decl * update) const;
|
func_decl * get_update_accessor(func_decl * update) const;
|
||||||
|
|
|
@ -2471,6 +2471,10 @@ cmd_context::dt_eh::dt_eh(cmd_context & owner):
|
||||||
|
|
||||||
void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) {
|
void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) {
|
||||||
TRACE(new_dt_eh, tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";);
|
TRACE(new_dt_eh, tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";);
|
||||||
|
|
||||||
|
// Batch initialize all constructor functions to avoid O(n²) behavior for large datatypes
|
||||||
|
m_dt_util.batch_initialize_constructor_functions(dt);
|
||||||
|
|
||||||
for (func_decl * c : *m_dt_util.get_datatype_constructors(dt)) {
|
for (func_decl * c : *m_dt_util.get_datatype_constructors(dt)) {
|
||||||
TRACE(new_dt_eh, tout << "new constructor: " << c->get_name() << "\n";);
|
TRACE(new_dt_eh, tout << "new constructor: " << c->get_name() << "\n";);
|
||||||
m_owner.insert(c);
|
m_owner.insert(c);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue