You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf: resolve a manifest's imports as one closure rooted at the manifest
A manifest is an ontology whose owl:imports name every member, so OntoEnv
can resolve the whole thing in one call instead of BuildingMOTIF
resolving each member's imports separately. Manifest.register() adds the
manifest graph to the ontology environment (idempotent, overwriting, ~4ms
for a graph of one triple per member) and Manifest.imports_closure()
returns the closure rooted at it: transitive and deduplicated, and flat
in the number of members where the old path was linear.
Measured on a Brick fixture + shape1.ttl (4,832-triple closure, 5 reps):
members one closure per-collection speedup
1 0.080s 0.146s 1.8x
2 0.077s 0.248s 3.2x
4 0.082s 0.390s 4.8x
End to end through validate(), where SHACL dominates: 1.24x (1 member)
and 1.77x (2). Results are identical -- a test asserts the manifest path
and the per-collection path report the same failures for the same focus
nodes on every engine.
Each member is taken from exactly one source. The closure supplies the
members OntoEnv knows; a member it does not know -- a directory-loaded
library, whose name is not an ontology URI, or one built with
Library.create -- contributes its own shape collection instead. Never
both: OntoEnv's copy and the library's shape collection hold the same
triples with different blank-node labels, so unioning them would
duplicate every SHACL property shape and report each violation twice.
Anything that resolves neither way raises OntologyImportsNotFound, the
same exception resolve_imports has always raised, honoring
error_on_missing_imports.
CompiledModel now carries the Manifest its shape collections came from
and resolves the closure lazily in validate(), because compiling does not
need the imports at all. Passing an explicit list of shape collections
keeps the per-collection path -- a bare list has no manifest to root a
closure at.
Inference input is deliberately unchanged: compile() still runs inference
against the member shape collections, not the closure. What a model
infers from should be the shapes it was compiled against, and pulling
every transitively imported ontology into the inference input would
change what lands in every compiled model.
Full unit suite: 570 passed, 1 skipped.
0 commit comments