Skip to main content

Sound, performant OWL 2 DL (SROIQ) reasoner in Rust — Python bindings

Project description

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, an IncompleteClassificationWarning is emitted and result.complete is False. Pass 0 for 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 like per_pair_timeout_ms=25 is 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 always complete (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 returned Classification — 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rustdl-0.3.20.tar.gz (1.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rustdl-0.3.20-cp310-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.10+Windows x86-64

rustdl-0.3.20-cp310-abi3-musllinux_1_2_x86_64.whl (2.5 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

rustdl-0.3.20-cp310-abi3-musllinux_1_2_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

rustdl-0.3.20-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

rustdl-0.3.20-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

rustdl-0.3.20-cp310-abi3-macosx_11_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file rustdl-0.3.20.tar.gz.

File metadata

  • Download URL: rustdl-0.3.20.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rustdl-0.3.20.tar.gz
Algorithm Hash digest
SHA256 681ca795a0a1484bd07f3b41063344860b64ebd535046862de916a03a7663808
MD5 011421bde1a7351c406c37d2e660710a
BLAKE2b-256 bd84788bddf2af41316113ef3bbecc1a7db6831fbc7a56379bd927543cd55d38

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20.tar.gz:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: rustdl-0.3.20-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 bbe88b8a7fae8c7d0993859d96447a9eb0f3498d14a54faa4bfd564090d324d2
MD5 3ba63743f3aec604b222cb0c60fafdb0
BLAKE2b-256 90cad4f37abf57db9a1f820595de22a42c4f01ec3fbb3032bc60b62f5ed4e01c

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-win_amd64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1bce0fcbe05fde651c2749dbf4dff863aa93d8acddeb71452a76c7897b2399d4
MD5 ec058f853ccd4ea56632cd15e41f396e
BLAKE2b-256 93eb3b1c01f43454a6f29beb3e4ddcce19e4cfcbfabd8b4de6f9aca1a10752f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-musllinux_1_2_x86_64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4be8352ff4a7446b592b668088f81e7781a4cfeeccc08a3ce9b6b9102956a297
MD5 f26f17816377706c1e6fd8b7ec45503e
BLAKE2b-256 15f29807118d1f56c9a3b15c78a5822cd2c23aad41665f5d58b7f73a5f72e997

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-musllinux_1_2_aarch64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 eddadec1a6f8762eee07d649ff0c71d9d0ededbe48d7df7f73afa475cf7a29b8
MD5 81d74809cf3d6631d6c0b0ead5c2a460
BLAKE2b-256 65f4165f25b64a952ec93be90984a9ffd37d51360cf445568ce4059a9a181c19

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7d2083785e6c0a4fccfdd403c174a41ba91c53656499fc2d7c446b00c3d01c84
MD5 6e9c29b0cfb7ae70b9cddfea3a77f4ea
BLAKE2b-256 3d5a51f68bd18be6cb9e6b5b5e3e7d7099ef77b314a321d67ff114d0339e4192

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rustdl-0.3.20-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.20-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d3dffae8f8f2c7c2f9fe6330e128d27b38c5288e6e9a1e7f0aba2a5d5d840a87
MD5 3e04a823f72d163bc41c96ac04095188
BLAKE2b-256 9e61e795aa09edf5e0414d5077d3a85fbbd9ac6ed2bf030a33268a0aaecb96b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.20-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release-python.yml on MaastrichtU-IDS/rustdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page