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.18.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.18-cp310-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.10+Windows x86-64

rustdl-0.3.18-cp310-abi3-musllinux_1_2_x86_64.whl (2.4 MB view details)

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

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

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

rustdl-0.3.18-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.18-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.18-cp310-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: rustdl-0.3.18.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.18.tar.gz
Algorithm Hash digest
SHA256 10ca35d4e8dd99f4ed975220ea8de00b627a3e1c8bd4f95f8d5919a5ed75bed3
MD5 4adbd66b36bdfc141586278558dd7753
BLAKE2b-256 5c2a51d232445e027f06060d7f0c8d09e6d8a45f3f6a529efa99dcaa7dc8f46b

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: rustdl-0.3.18-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.18-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 05b5e8fe4de2c2c321df5a7de43e3e71e82a4eca0b331dabec4d4d412dfcfd14
MD5 35e25d6bdcfee9e958180479b9ce0322
BLAKE2b-256 77946072bfdc2792815c8bbf3cff0b5c4d01e4f23a72d989e981f0a8da873566

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for rustdl-0.3.18-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3c9a1dd4946e833485c49d975c3521866069d86351dd2d0d227e2d7da9232ed6
MD5 9598309dcbd38c735f4f2ea9d582ba1e
BLAKE2b-256 6359ef3aef665af7d1ae9c421489e45457d188a06c8a226b504b28d148bec271

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for rustdl-0.3.18-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ba4c4777412693fd4048d55c2e40610e0f7d3a7df2d47ae9cd8f0fa89c1a80a3
MD5 ab27c4bb344fe0af21614bebbd9af62a
BLAKE2b-256 d1b52d6115c400ba913aae7c2542940d4d1c309b2c4d8716fba061088590aa34

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for rustdl-0.3.18-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e85281c772ede269863e0c9f5cc4a491ac0e80c25940ecd7132044a6332783d1
MD5 b32dbbdde92e2e7f686c6d2d8b0d4323
BLAKE2b-256 e5f9ae54879cb4d7ffdd39283e4f2df175c7d64c221296e7a36d91022651ec98

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for rustdl-0.3.18-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f9089fb18a7bba3af68316fd4d79e66756a03c04f4c8eeb86393c07e6596de5b
MD5 8c82f60b7aaa80981e723195951e927d
BLAKE2b-256 c13e4d62d8479a98d492697a7f4ea0b79e6a672022d2aa50e9c1f24aa103318c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for rustdl-0.3.18-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7d075203984571e3650fe9b25807a1b647287110449b1c530aebe46bb46b8f30
MD5 1a693b001d47b8394ae47cc07e1dd5b8
BLAKE2b-256 b1ba3c798460078262f69db20c514186991c9f72d2185c8b2e8f8d180a691b45

See more details on using hashes here.

Provenance

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