Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

PyHermit: Python OWL 2 DL Reasoner

License: Apache-2.0 Python 3.10+

PyHermit is a Python port of HermiT, an OWL 2 DL reasoner developed at the University of Oxford. It reasons about OWL ontologies with tableau-based decision procedures and needs no JVM.

Features

  • OWL 2 DL reasoning: a tableau decision procedure over the OWL 2 Direct Semantics constructs.
  • Tableau algorithm: hyperresolution with configurable blocking strategies.
  • Non-simple property validation: the OWL 2 spec forbids transitive, role-chain, and inherited-superrole properties in cardinality restrictions, hasSelf, asymmetric, irreflexive, or disjoint axioms. PyHermit rejects these at clausification time with a ValueError.
  • All OWL 2 datatypes: xsd:string, decimal, integer, float, double, dateTime, boolean, anyURI, and more.
  • SWRL rules and Datalog queries: DL-safe rule support with query evaluation.
  • OWL file parsing: load RDF/XML, OWL/XML, and Functional-Style Syntax through a pure stdlib reader (hermit.parser.load_ontology).
  • Pure Python: no JVM, no external binaries, a single pip install.
  • Full type hints: the code passes mypy --strict.

Install

pip install hermit-reasoner

Basic usage

from hermit import Reasoner
from hermit.model import AtomicConcept, AtomicRole, Individual
from hermit.owl_model.class_expression import OWLClass
from hermit.owl_model.owl_individual import OWLNamedIndividual
from hermit.owl_model.owl_property import OWLObjectProperty
from hermit.owl_model.owl_axiom import (
    OWLClassAssertionAxiom, OWLObjectPropertyAssertionAxiom, OWLSubClassOfAxiom,
)
from hermit.structural.owl_clausification import OWLClausification
from hermit.structural.owl_normalization import OWLNormalization

NS = "http://example.org/"
Animal = OWLClass(NS + "Animal")
Dog = OWLClass(NS + "Dog")
hasOwner = OWLObjectProperty(NS + "hasOwner")
fido = OWLNamedIndividual(NS + "fido")
john = OWLNamedIndividual(NS + "john")

axioms = [
    OWLSubClassOfAxiom(Dog, Animal),
    OWLClassAssertionAxiom(fido, Dog),
    OWLObjectPropertyAssertionAxiom(fido, hasOwner, john),
]

normalized = OWLNormalization().process_ontology(axioms)
dl_ontology = OWLClausification().clausify(normalized, ontology_iri="urn:example:pets")

reasoner = Reasoner(dl_ontology)
reasoner.precompute_inferences()

animal = AtomicConcept.create(NS + "Animal")          # query handles
fido_h = Individual.create(NS + "fido")

assert reasoner.is_consistent()
assert reasoner.has_type(fido_h, animal)              # inferred
assert reasoner.has_role_relationship(
    fido_h, AtomicRole.create(NS + "hasOwner"), Individual.create(NS + "john")
)
instances = reasoner.get_instances(animal)            # {fido}
reasoner.dispose()

Load from OWL files

from hermit.parser import load_ontology
from hermit.structural.owl_normalization import OWLNormalization
from hermit.structural.owl_clausification import OWLClausification
from hermit import Reasoner

axioms = load_ontology("path/to/ontology.owl")  # stdlib reader: RDF/XML, OWL/XML, FSS

normalized = OWLNormalization().process_ontology(axioms)
dl_ontology = OWLClausification().clausify(normalized)  # raises ValueError on OWL 2 violations

reasoner = Reasoner(dl_ontology)
reasoner.precompute_inferences()

Architecture

OWL Ontology
    |
    v
OWLNormalization  (NNF, fresh-concept introduction, simple/complex property classification)
    |
    v
OWLClausification (DL clauses, non-simple property validation via ObjectPropertyInclusionManager)
    |
    v
Tableau Expansion (hyperresolution with blocking)
    |
    v
Classification & Instance Retrieval

See docs/ for architecture detail and API reference.

Non-simple property enforcement

OWL 2 forbids non-simple properties (transitive, or a superrole of a role chain) in certain axiom positions. PyHermit enforces this at clausification time:

from hermit.structural.owl_clausification import OWLClausification

clausification = OWLClausification()
try:
    dl_ontology = clausification.clausify(normalized)
except ValueError as e:
    # e.g. "Non-simple property '...' cannot be asymmetric (OWL 2 violation)"
    print(e)

PyHermit checks these constraints, per OWL 2 spec Section 11.2:

  • AsymmetricObjectProperty
  • IrreflexiveObjectProperty
  • DisjointObjectProperties
  • Cardinality restrictions (ObjectMinCardinality, ObjectMaxCardinality, ObjectExactCardinality)
  • ObjectHasSelf

Source: ObjectPropertyInclusionManager._validate_complex_property_constraints, at src/hermit/structural/object_property_inclusion_manager.py:360.

Project status

PyHermit is a structural port of Java HermiT. The reasoning core is implemented: tableau, blocking, hyperresolution, classification, datatype reasoning, and SWRL/Datalog query answering. Ontology loading uses a pure stdlib reader (RDF/XML, OWL/XML, Functional-Style Syntax).

  • TBox reasoning (classification, subsumption)
  • ABox instance retrieval
  • Datatype reasoning
  • SWRL rules and Datalog query answering
  • Non-simple property validation
  • OWL file parsing through a pure stdlib reader (RDF/XML, OWL/XML, FSS)

Conformance: PyHermit passes 340 of 350 W3C OWL WG Approved-DL test cases at a 20-second per-case budget. Run this with pytest -m slow tests/test_wg_conformance.py, or python scripts/wg_run.py approved --list-fails --timeout=20. It reports zero wrong answers, zero errors, and zero unchecked conclusions. The 10 non-passing cases time out on hard combinatorial ontologies. Several of them pass with the 300-second budget the Java harness uses. FAITHFULNESS_AUDIT.md documents intentional divergences from the Java original.

The unit suite passes under pytest (the W3C conformance corpus is marked slow and excluded by default). The code passes mypy --strict and ruff.

Documentation

Related projects

License

Apache 2.0. See LICENSE.

Based on HermiT, copyright Oxford University Computing Laboratory 2008-2014.

Download files

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

Source Distribution

hermit_reasoner-0.3.1a2.tar.gz (290.5 kB view details)

Uploaded Source

Built Distribution

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

hermit_reasoner-0.3.1a2-py3-none-any.whl (353.1 kB view details)

Uploaded Python 3

File details

Details for the file hermit_reasoner-0.3.1a2.tar.gz.

File metadata

  • Download URL: hermit_reasoner-0.3.1a2.tar.gz
  • Upload date:
  • Size: 290.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hermit_reasoner-0.3.1a2.tar.gz
Algorithm Hash digest
SHA256 79041553400ee876230b2fe2903b71637511d0afa8097b0b36cf6444268cdf32
MD5 7281a6e056334129c345fe584978a09a
BLAKE2b-256 0b527a62fb7f0db70a8861bad39f075a799285c8d53c1cf5f04db740ad835907

See more details on using hashes here.

File details

Details for the file hermit_reasoner-0.3.1a2-py3-none-any.whl.

File metadata

File hashes

Hashes for hermit_reasoner-0.3.1a2-py3-none-any.whl
Algorithm Hash digest
SHA256 8c3aed3af9da5684ea0ccb6747d3bfffe80468df1b57654e7a07bb70fe7ff4d1
MD5 eab1d82c0f65f9da07a3195610ff3144
BLAKE2b-256 ae4c319ae0d7527a3bfaa1ef66d41cfcd0a1ebc998a354daf9102b3b0c1a5271

See more details on using hashes here.

Supported by

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