rustdl
Sound, performant OWL 2 DL (SROIQ) reasoner in Rust, with Python bindings. No JVM, no subprocess — native classification via PyO3.
rustdl beats HermiT on every measured ORE workload and wins outright against
Konclude on Horn-fragment ontologies. See the
project README for the full
benchmark table.
Install
pip install rustdl
Wheels are published for CPython 3.10+ on Linux (x86_64, aarch64), macOS (Apple Silicon), and Windows (AMD64). Other platforms build from the sdist (needs a Rust toolchain).
Quick start
Prefer a guided walkthrough? See Debugging an ontology with rustdl — an end-to-end QA tutorial (classify →
debug()→ justify/repair → fix → read inferred facts).
import rustdl
# A small OWL 2 DL ontology ships inside the wheel (gzip-compressed) — no
# download needed. `examples.pizza()` returns its file path (decompressed
# into a per-user cache dir on first use); `examples.PIZZA_NS` is its
# namespace, so class IRIs are PIZZA_NS + local name (e.g. + "Pizza").
from rustdl.examples import pizza, PIZZA_NS, SULO_NS
# Classify. Format is auto-detected from the extension:
# .ofn (OWL Functional), .owx (OWL/XML), .rdf / .owl (RDF/XML), .omn (Manchester).
result = rustdl.classify(pizza())
print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable, "
f"complete={result.complete}")
# -> 88 classes, 0 unsatisfiable, complete=True
# Query the computed hierarchy
print(result.is_subclass(PIZZA_NS + "BoxedPizza", PIZZA_NS + "Pizza"))
# -> True
print(len(result.subclasses_of(PIZZA_NS + "FoodMaterial")))
# -> 25
# The pizza ontology is aligned to the SULO upper ontology, so reasoning
# spans both — e.g. a pizza-making timestamp is inferred to be a SULO StartTime:
print(result.is_subclass(PIZZA_NS + "BakingStartTime", SULO_NS + "StartTime"))
# -> True
# Other hierarchy queries (all take full class IRIs):
result.superclasses_of(PIZZA_NS + "Cheese") # -> list[str]
result.equivalent_classes(PIZZA_NS + "Pizza") # -> list[str]
result.direct_subsumers(PIZZA_NS + "BoxedPizza") # -> list[str] (Hasse-direct parents)
Bundled examples
Three real ontologies ship inside the wheel, gzip-compressed (~200 KB total).
They classify with no network access — each examples.X() decompresses
its ontology into a per-user cache dir ($XDG_CACHE_HOME/rustdl/examples or
~/.cache/rustdl/examples) on first use, then reuses it. Each examples.X_NS
is the namespace, so a class IRI is the namespace plus the local name.
| helper | ontology | classes | notes |
|---|---|---|---|
pizza() / PIZZA_NS |
ontostart pizza | 88 | SULO-aligned pizza-making ontology; classifies instantly + complete |
sulo() / SULO_NS |
SULO (Simple Upper-Level Ontology) | 17 | tiny; classifies in milliseconds |
sio() / SIO_NS |
SIO (Semanticscience Integrated Ontology) | ~1600 | realistic larger workload; takes tens of seconds. Class IRIs are numeric codes, e.g. SIO_NS + "SIO_000006" ("process") |
import rustdl
from rustdl import examples
r = rustdl.classify(examples.sulo())
print(r.is_subclass(examples.SULO_NS + "StartTime", examples.SULO_NS + "Object"))
# -> True
API
Classification
result = rustdl.classify(path, *, per_pair_timeout_ms=1000, saturation_only=False)
result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=1000, saturation_only=False)
per_pair_timeout_ms— bound each subsumption test (default 1000;0= unbounded). A pair that exceeds the budget is recorded as "not subsumed": sound (never a false subsumption) but the result may be incomplete. When that happens, anIncompleteClassificationWarningis emitted andresult.completeisFalse. Pass0for the complete, unbounded classification. The default bounds pathological SROIQ inputs so classification can't hang silently. Conversely, on nominal-heavy ontologies (e.g. the W3C wine ontology) the engines never terminate on the hard pairs and only burn the full budget, so a low value likeper_pair_timeout_ms=25is much faster with no completeness loss (wine: 7.5× faster, identical hierarchy, MISSED=0 vs HermiT).saturation_only— skip the tableau entirely; EL-closure-only under-approximation. Dramatically faster on mostly-EL ontologies, and alwayscomplete(no tableau ⇒ no timeout).
classify / classify_bytes return a Classification:
| member | type | meaning |
|---|---|---|
.classes |
list[str] |
all declared class IRIs |
.unsatisfiable |
list[str] |
classes proved ⊑ ⊥ |
.inconsistent |
bool |
whole ontology unsatisfiable |
.complete |
bool |
False if any pair hit the timeout (result may miss edges) |
.timed_out_pairs |
int |
how many pairs hit the timeout |
.is_subclass(sub, sup) |
bool |
is sub ⊑ sup entailed? |
.subclasses_of(cls) |
list[str] |
every D with D ⊑ cls |
.superclasses_of(cls) |
list[str] |
every D with cls ⊑ D |
.equivalent_classes(cls) |
list[str] |
classes equivalent to cls |
.direct_subsumers(cls) |
list[str] |
Hasse-direct parents of cls |
One-shot queries
Each parses the file, answers one question, and returns:
rustdl.is_consistent(path) # -> bool
rustdl.is_class_satisfiable(path, class_iri) # -> bool
rustdl.is_subclass_of(path, sub_iri, sup_iri) # -> bool
rustdl.is_instance_of(path, class_iri, indiv_iri) # -> bool
rustdl.instances_of(path, class_iri) # -> list[str]
rustdl.realize(path) # -> dict[str, list[str]]
realize returns each individual IRI mapped to its most-specific entailed
class IRIs.
For repeated queries over the same ontology, prefer
classify(path)once and query the returnedClassification— each top-level function re-parses.
Inference materialization
rustdl.materialize_inferred_subclass_axioms(path) # -> list[tuple[str, str]]
rustdl.materialize_inferred_class_assertions(path) # -> list[tuple[str, str]]
materialize_inferred_subclass_axioms yields (sub, sup) pairs for every
entailed subsumption (excluding reflexive, owl:Thing/owl:Nothing, and
unsatisfiable classes). materialize_inferred_class_assertions yields
(class, individual) pairs. Useful for writing an inferred ontology back to
disk.
Errors
rustdl.RustdlError # base — catches everything from the library
rustdl.ParseError # the OWL file couldn't be parsed
rustdl.UnsupportedAxiomError # HasKey, role chains > length 2, etc.
rustdl.UnknownClassError # an IRI argument isn't a declared class
try:
result = rustdl.classify("ontology.ofn")
except rustdl.ParseError as e:
print(f"bad input: {e}")
except rustdl.RustdlError as e:
print(f"reasoning failed: {e}")
Soundness & coverage
rustdl is sound: every reported subsumption is a genuine entailment
(FP=0 against Konclude on the validation corpus). Completeness is partial — the
default classifier is empirically near-complete across the measured corpus but
not provably complete on all of SROIQ. saturation_only and
per_pair_timeout_ms are sound-but-incomplete by construction.
Data-property and datatype axioms outside the recognized preprocessing patterns
are silently dropped (a sound under-approximation). HasKey and role chains
longer than length 2 raise UnsupportedAxiomError. SWRL rules are skipped.
See the project documentation for the full coverage matrix, soundness contract, and architecture notes.
License
Apache-2.0 OR MIT.
Release files for rustdl 0.4.29
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rustdl-0.4.29.tar.gz | 1.7 MB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rustdl-0.4.29-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| rustdl-0.4.29-cp310-abi3-musllinux_1_2_x86_64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ x86-64 | Details |
| rustdl-0.4.29-cp310-abi3-musllinux_1_2_aarch64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ ARM64 | Details |
| rustdl-0.4.29-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rustdl-0.4.29-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| rustdl-0.4.29-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 18.1 MB
Release files / rustdl-0.4.29.tar.gz
| Download URL | rustdl-0.4.29.tar.gz |
|---|---|
| Size | 1.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ebedac01b7793b3f8f5a1a2541a4340c622ef8b3da9c869c2cde6d9ddfc2a36
|
|
BLAKE2b-256 checksum How to use checksums |
a5c03433db1e53495e99ede5a72377b6cc8b9172b97bd539c99c404e90c0743b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-win_amd64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
6d977a80e505cdaa456f91b68f267a40929b4e81bbbba08c2686163fe5093b6c
|
|
BLAKE2b-256 checksum How to use checksums |
721446b17977c3d468fb328dbf40aa5b13e9c53663d3d673168ef5ab703c97a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
cd614ca57f9b4293141b16e8408e7536dbb5949b41fe2dd7ac54889191f6f45a
|
|
BLAKE2b-256 checksum How to use checksums |
8b931de4ed78aa2f0f6805281c59f3df5d03007d74b14141bea38892e57511e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
c636f179180a0f0b7bb8e14023bab820533d3f0a466dd9fc7771f956a71c96ae
|
|
BLAKE2b-256 checksum How to use checksums |
c18bf1187d10adfda37bbfce035fff0cbce0424b7cae6fd4e22c5e40a9f329ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.8 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8b2420983dc8d89f243ae3d7b6f0ec4078bb75cb71a2c0b9fb762ed2dc446704
|
|
BLAKE2b-256 checksum How to use checksums |
85eb9d7f2ca9161ee4ccf2c3aab9b71eac449702f1d257a090d8ab80a46b3d55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
82ac76ca8f4a3a38c3fb886dbfd97b91b5dae12f8b0cd32a2cdbabbee370bb8b
|
|
BLAKE2b-256 checksum How to use checksums |
a70a8fb3ca496179ae57cc7fd63ad4948db5d5532d47b81773d82c7fd05413dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / rustdl-0.4.29-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | rustdl-0.4.29-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e8fa7e8709d1f96bdb9cbe9dc6bc46f296542c5c12ad8b1b5a3c7ab0c432b697
|
|
BLAKE2b-256 checksum How to use checksums |
ce0a9a0e7ea2eeb77b8a86ae94ec8bc2a77256be8f4b8e3f0f2e5ef7ba10eb79
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency log