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: LGPL-3.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

LGPL-3.0-or-later, matching upstream HermiT. 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.1a4.tar.gz (289.2 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.1a4-py3-none-any.whl (351.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hermit_reasoner-0.3.1a4.tar.gz
  • Upload date:
  • Size: 289.2 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.1a4.tar.gz
Algorithm Hash digest
SHA256 46468e960b0708f849f05ab3474cc7f04f74cfca6c651a0c5d0d677040b42111
MD5 a7323478fcd4431faf87488ac2d8929a
BLAKE2b-256 8d9e36807b92447e75bd7d5c1d1015028f82d3316a9f0782ff39e92ef4b83d6e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for hermit_reasoner-0.3.1a4-py3-none-any.whl
Algorithm Hash digest
SHA256 027f46b82a3443ecf1688c9dd4c8135f670c0e537a12cb3fe127e1ed259fd2a6
MD5 8959a97769e804ce5a2c0e912d347cad
BLAKE2b-256 d071d2676bcb643918719a29c550e897204c6a1542078288a403bbd61d4d7482

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