Reasoners

To validate facts about statements in the ontology, the help of a reasoner component is required.

For this guide we will also consider the ‘father’ ontology that we slightly described here:

from owlapy.iri import IRI
from owlapy.owl_ontology_manager import OntologyManager

manager = OntologyManager()
onto = manager.load_ontology(IRI.create("KGs/Family/father.owl"))

In our Owlapy library, we provide two main reasoner classes:

  • StructuralReasoner (What used to be FastInstanceCheckerReasoner )

    Structural Reasoner is the base reasoner in Owlapy. This reasoner works under CWA/PCWA and the base library used for it is owlready2. The functionalities of this reasoner are limited and may be incomplete. It does not provide full reasoning in ALCH. It provides support for finding instance of complex class expression. It has a cache storing system that allows for faster execution of some reasoning functionalities.

    Initialization:

    from owlapy.owl_reasoner import StructuralReasoner
    
    structural_reasoner = StructuralReasoner(onto, property_cache = True, negation_default = True, sub_properties = False)
    

    The structural reasoner requires an ontology (AbstractOWLOntology). property_cache specifies whether to cache property values. This requires more memory, but it speeds up the reasoning processes. If negation_default argument is set to True the missing facts in the ontology means false. The argument sub_properties is another boolean argument to specify whether you want to take sub properties in consideration for instances() method.

  • SyncReasoner

    SyncReasoner is a class that serves as a ‘syncing’ class between our framework and reasoners in owlapi. It can perform full reasoning in ALCH due to the use of reasoners from powerful reasoners like HermiT, Pellet, etc. SyncReasoner is more useful when your main goal is reasoning over the ontology, and you are familiarized with the java reasoners (HermiT, Pellet, JFact, Openllet, …).

    Initialization:

    from owlapy.owl_reasoner import SyncReasoner
    
    sync_reasoner = SyncReasoner(ontology="KGs/Mutagenesis/mutagenesis.owl", reasoner="HermiT")
    

    SyncReasoner is made available by owlapi mapper and requires the ontology path or an object of type SyncOntology, together with a reasoner name from the possible set of reasoners: "Hermit", "Pellet", "JFact", "Openllet" "StructuralReasoner".

    Note that SyncReasoner with reasoner argument set to "StructuralReasoner" is refering to StructuralReasoner implemented in owlapi. That is different from our StructuralReasoner.

Usage of the Reasoner

All the reasoners available in the Owlapy library inherit from the class: AbstractOWLReasoner. Further on, in this guide, we use StructuralReasoner to show the capabilities of a reasoner in Owlapy.

We will proceed to use the father dataset to give examples.

Class Reasoning

Using an AbstractOWLOntology you can list all the classes in the signature, but a reasoner can give you more than that. You can get the subclasses, superclasses or the equivalent classes of a class in the ontology:

from owlapy.class_expression import OWLClass
from owlapy.iri import IRI

namespace = "http://example.com/father#"
male = OWLClass(IRI(namespace, "male"))

male_super_classes = structural_reasoner.super_classes(male)
male_sub_classes = structural_reasoner.sub_classes(male)
male_equivalent_classes = structural_reasoner.equivalent_classes(male)

We define the male class by creating an OWLClass object. The methods super_classes and sub_classes have 2 more boolean arguments: direct and only_named. If direct=True then only the direct classes in the hierarchy will be returned, else it will return every class in the hierarchy depending on the method(sub_classes or super_classes). By default, its value is False. The next argument only_named specifies whether you want to show only named classes or complex classes as well. By default, its value is True which means that it will return only the named classes.

NOTE: The extra arguments direct and only_named are also used in other methods that reason upon the class, object property, or data property hierarchy.

NOTE: In SyncReasoner, there is no use for the argument only_named as this is not supported by methods in the java library owlapi.

You can get all the types of a certain individual using types method:

anna = list(onto.individuals_in_signature()).pop(0)

anna_types = structural_reasoner.types(anna)

We retrieve anna as the first individual on the list of individuals of the ‘Father’ ontology. The type method only returns named classes.

Object Properties and Data Properties Reasoning

Owlapy reasoners offers some convenient methods for working with object properties and data properties. Below we show some of them, but you can always check all the methods in the AbstractOWLReasoner class documentation.

You can get all the object properties that an individual has by using the following method:

anna = individuals[0] 
object_properties = structural_reasoner.ind_object_properties(anna)

In this example, object_properties contains all the object properties that anna has, which in our case would only be hasChild. Now we can get the individuals of this object property for anna.

for op in object_properties:
    object_properties_values = structural_reasoner.object_property_values(anna, op)
    for individual in object_properties_values:
        print(individual)

In this example we iterated over the object_properties, assuming that there are more than 1, and we use the reasoner to get the values for each object property op of the individual anna. The values are individuals which we store in the variable object_properties_values and are printed in the end. The method object_property_values requires as the first argument, an OWLNamedIndividual that is the subject of the object property values and the second argument an OWLObjectProperty whose values are to be retrieved for the specified individual.

NOTE: You can as well get all the data properties of an individual in the same way by using ind_data_properties instead of ind_object_properties and data_property_values instead of object_property_values. Keep in mind that data_property_values returns literal values (type of OWLLiteral).

In the same way as with classes, you can also get the sub object properties or equivalent object properties.

from owlapy.owl_property import OWLObjectProperty

hasChild = OWLObjectProperty(IRI(namespace, "hasChild"))

equivalent_to_hasChild = structural_reasoner.equivalent_object_properties(hasChild)
hasChild_sub_properties = structural_reasoner.sub_object_properties(hasChild)

In case you want to get the domains and ranges of an object property use the following:

hasChild_domains = structural_reasoner.object_property_domains(hasChild)
hasChild_ranges = structural_reasoner.object_property_ranges(hasChild)

NOTE: Again, you can do the same for data properties but instead of the word ‘object’ in the method name you should use ‘data’.

Find Instances

The method instances is a very convenient method. It takes only 1 argument that is basically a class expression and returns all the individuals belonging to that class expression. In Owlapy we have implemented a Python class for each type of class expression. The argument is of type OWLClassExpression.

Let us now show a simple example by finding the instances of the class male and printing them:

male_individuals = structural_reasoner.instances(male)
for ind in male_individuals:
    print(ind)

In this guide we covered the main functionalities of the reasoners in Owlapy. In the next one, we speak about owlapi synchronization and how can make use of owlapi in owlapy.