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.33.tar.gz (1.2 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.33-cp310-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.10+Windows x86-64

rustdl-0.3.33-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.33-cp310-abi3-musllinux_1_2_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

rustdl-0.3.33-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.33-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.33-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.33.tar.gz.

File metadata

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

File hashes

Hashes for rustdl-0.3.33.tar.gz
Algorithm Hash digest
SHA256 5003a717d8f9fab9a4b24aa5906fdd5913de85c6103d9e8a9464bf83ca7f95f2
MD5 a33baa9c89089fb2cc7e237799bbcab4
BLAKE2b-256 d2eb9a3ce77bfe907c7013432def4446a4a859e5066fc7171cf31b3b03997ddd

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33.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.33-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: rustdl-0.3.33-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.14

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f209b92ced94bd5425073c9fb8999d1e2c860aded14d6a1d5652543ae1f19cee
MD5 ae6228dec8d03875eca1aec7ae2e6370
BLAKE2b-256 33dc1ce7a283772420c5188ffee9473526afd020cbb3121afbecff4e4af7ee28

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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.33-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 bc4e9102c7b1a96c4314cedefc2ef0525c67895259fe36d5496c2792a03bb0d9
MD5 8f4d4f5f5bf27b0dd093b8780b3ff25c
BLAKE2b-256 7862a704711af87872a179b0b72ea6ba83493d61ae8bf5a8a4ace170acdf97ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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.33-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 cd44f4c1f55569f5889abe530af5e80713a5304adbcdcb89172d5f876c597793
MD5 23d621bfdf63da8d7b2c46680d0f14f2
BLAKE2b-256 b1a19ef317d75257be997ab3ac5acc2b351beba77122e568829688626c887a22

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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.33-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6df5e8e796a5493948f3ef3841b6978c8f6b27dbdbe4ec79ad1098151727e417
MD5 43e0745abdce3a01df3125870bd0fc9e
BLAKE2b-256 f83556d68402be847ba421b98b2a7c963bc55e89bb7afad12769636a9e6f9329

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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.33-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 54ae55879a9547145fd38e0ed5c88fae5fdc6c8731d361d12e85eb695fdb95d0
MD5 94ed27c5dd9056160398d824ef1e1499
BLAKE2b-256 acb4f0403b87a05c55b48fab1c2ad1a4636d8cb316c66b9411fd279d12921120

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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.33-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rustdl-0.3.33-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b4e6c8086d849e9d7904e5b4ebe680c527f643c3e531c06be3813bfef2ddfa4d
MD5 da4d0f05c6c3d500b6d5a9b86b45b594
BLAKE2b-256 beeb413d2ff56c7fc529eb1fe6f0434d8f8526e62cb4fd238221389581393abf

See more details on using hashes here.

Provenance

The following attestation bundles were made for rustdl-0.3.33-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