protege logo
      HOME |  OVERVIEW |  DOCUMENTATION |  DOWNLOADS |  SUPPORT |  COMMUNITY |  WIKI |  ABOUT US
USERS
DEVELOPERS


see also:
CORE PROTEGE API
PROTEGE-OWL API
PROTEGE WIKI
SWRL TAB
 using the protégé-owl reasoner api

This page describes the Reasoning API for Protege versions prior to 3.4 beta 120 (from 2007/11/17).
For Protege versions after 2007/11/17 please refer to this updated page.


In addition to providing an API that facilitates programmatic exploration and editing of OWL ontologies, Protégé-OWL features a reasoning API, which can be used to access an external DIG compliant reasoner, thereby enabling inferences to be made about classes and individuals in an ontology. This brief tutorial describes how Protégé-OWL communicates with a reasoner, and provides an example of how to use the Protégé-OWL reasoning API.

Description Logic Reasoners

OWL-DL has its foundations in Description Logics, which are decidable fragments of First Order Logic. For a particular task, a logic is decidable if it is possible to design an algorithm that will terminate in a finite number of steps (i.e., the algorithm is guaranteed not to run forever). For example, in Description Logic it is possible to write an algorithm that calculates whether or not one concept is a subclass of another concept, which is guaranteed to terminate after a finite number of steps. Because an OWL-DL ontology can be translated into a Description Logic representation, it is possible to perform automated reasoning over the ontology using a Description Logic reasoner. A Description Logic reasoner performs various inferencing services, such as computing the inferred superclasses of a class, determining whether or not a class is consistent (a class is inconsistent if it cannot possibly have any instances), deciding whether or not one class is subsumed by another, etc. Some of the popular Descrioption Logic reasoners that are available are listed below:


A more comprehensive list of Description Logic reasoners is maintained by Uli Sattler at the University of Manchester.

DIG Compliant Description Logic Reasoners

Because a) writing a Description Logic reasoner is a non-trival task, and b) highly optimized third party Description Logic reasoners have already been developed, it does not make sense to write a reasoner for a specific application. Fortunately, a standard exists that provides a specification for a common way of connecting to third party DL reasoners. This standard is called the "DIG interface" (DIG is short for DL Implementation Group). A DIG compliant reasoner is a Description Logic reasoner that provides a standard access interface (a.k.a. the DIG interface), which enables the reasoner to be accessed over HTTP, using the DIG langauge. The DIG language is an XML based representation of ontological entities such as classes, properties, and individuals, and also axioms such as subclass axioms, disjoint axioms, and equivalent class axioms. The DIG langauge contains constructs that allow clients to "tell" a reasoner about an ontology (i.e., describe an ontology to a reasoner), and also "ask" a reasoner about what it has inferred, such as subclass releationships, type relationships, etc. An example of the DIG language (DIG 1.1) is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<tells uri="" xmlns="http://dl.kr.org/dig/2003/02/lang"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://potato.cs.man.ac.uk/dig/level0/dig.xsd">
    <equalc>
        <catom name="owl:Thing"/>
        <top/>
    </equalc>
    <defconcept name="ParmezanTopping"/>
    <equalc>
        <catom name="ParmezanTopping"/>
        <and>
            <catom name="CheeseTopping"/>
            <some>
                <ratom name="hasSpicyness"/>
                <catom name="MildSpiciness"/>
            </some>
        </and>
    </equalc>
    <disjoint>
        <catom name="ParmezanTopping"/>
        <catom name="MozzarellaTopping"/>
    </disjoint>
    <disjoint>
        <catom name="ParmezanTopping"/>
        .
        .
        .
The advantage of DIG is that applications can communicate with any DIG compliant reasoner, without needing to know specific reasoner details or reasoner interaction protocols. This means that it is possible to "plug in" any DIG compliant reasoner into any DIG aware application. For example, RACER, FaCT++ or any other DIG compliant reasoner may be used with Protégé-OWL.

Protégé-OWL provides an API that can be used to interact with an external DIG reasoner. Fortunately for developers, the Protégé-OWL reasoning API abstracts away from the DIG language/reasoner, meaning that it is not really necessary to know the fine grained details of DIG, or that the reasoning services are being provided by an external DIG reasoner.

The Reasoning API

The following sections provide a rough outline of how to use the Protégé-OWL reasoning API. The examples use an ontology that describes pizzas, which can be downloaded from the CO-ODE Web site at the University of Manchester. This ontology is roughly based on the "Pizzas" ontology that is constructed in the popular Protégé-OWL tutorial, written by Matthew Horridge of the University of Manchester.

The inference Package

The reasoning API is encapsulated in the edu.stanford.smi.protegex.owl.inference package. The main classes that will be used are the ReasonerManager (used to obtain a reasoner) and ProtegeOWLReasoner (an interface to the external DIG reasoner). More information about downloading the Protégé-OWL source code is available on the main developer documentation page.

The Reasoner Manager

In general, the first step when using the reasoning API is to obtain an instance of ProtegeOWLReasoner for an OWL model. This instance of the reasoner can then be used to obtain inferred information about the model such as inferred superclasses, inferred equivalent classes, and inferred types for individuals. The ProtegeOWLReasoner manages communication with the external DIG reasoner, ensuring that it is always properly synchronised with the internal Protégé-OWL model.

In order to get an instance of ProtegeOWLReasoner for an OWL model, the ReasonerManager, which is found in the edu.stanford.smi.protegex.owl.inference.protegeowl package, must be used. The ReasonerManager is a singleton class (a class with only one instance), whose instance can be obtained by using the static method getInstance().

The getReasoner(OWLModel kb) method on the ReasonerManager can be used to obtain the reasoner for the specified OWLModel. This method will return the same instance of ProtegeOWLReasoner for a given model each time it is called. An alternative method getReasoner(OWLModel kb, boolean createNew) may be used to obtain a reasoner for a knowledge base. If the createNew flag is set to true, then this method will create a brand new instance of ProtegeOWLReasoner for the specified knowledge base. In general, the former method is preferred since the default implementation of ProtegeOWLReasoner only synchronizes the external DIG reasoner with the Protégé-OWL model when necessary (when changes have occurred to the OWL model) - creating a new reasoner every time will cause the external DIG reasoner to be resynchronised every time, which could be costly in terms of time for large ontologies. The code snippet below shows how to obtain a ProtegeOWLReasoner for an OWLModel:
// Get the reasoner manager and obtain a reasoner for the OWL model.
ReasonerManager reasonerManager = ReasonerManager.getInstance(); 
ProtegeOWLReasoner reasoner = reasonerManager.getReasoner(model);
Setting and Checking the Reasoner Connection

Communication with an external DIG compliant reasoner is facilitated over HTTP, so the URL of the external DIG Reasoner needs to be provided. This is done with the setReaonerURL(String url) method on ProtegeOWLReasoner. Having set the URL, the connection may be tested using the isConnected() method. An example is shown in the following code snippet:

// Set the reasoner URL (using the default URL for Racer here) and test the connection.
reasoner.setURL(http://localhost:8080);
if (reasoner.isConnected()) { 
    // Get the reasoner identity - this contains information 
    // about the reasoner, such as it's name and version,
    // and the tell and ask operations that it supports.
    DIGReasonerIdentity reasonerIdentity = reasoner.getIdentity(); 
    System.out.println("Connected to " + reasonerIdentity.getName()); 
}
Querying the Reasoner for Inferred Information

Once the connection to a reasoner has been established, the reasoner can be queried for information about the ontology. The ProtegeOWLReasoner interface contains several methods to obtain inferred information about classes and individuals. For example, there are methods to get the inferred superclasses and subclasses of a given class. The example below shows how to get the inferred subclasses for a specific class, in this case VegetarianPizza, which is a named class in the Pizza ontology. First, the asserted named subclasses of VegetarianPizza are retrieved via the OWLModel using vegetarianPizza.getNamedSubclasses(). In the case of this example, the number of asserted subclasses should be zero. Next, the inferred subclasses of VegetarianPizza are retrieved by querying the reasoner, and are then are printed out.

// Get the VegetarianPizza OWLNamedClass from the OWLModel 
OWLNamedClass vegetarianPizza = model.getOWLNamedClass("VegetarianPizza"); 
if (vegetarianPizza != null) { 
    // Get the number of asserted subclasses of VegetarianPizza 
    Collection assertedSubclasses = vegetarianPizza.getNamedSubclasses(); 
    System.out.println("Number of asserted VegetarianPizzas: " + assertedSubclasses.size()); 
 
    // Now get the inferred subclasses of VegetarianPizza 
    Collection inferredSubclasses = reasoner.getSubclasses(vegetarianPizza, null); 
    System.out.println("Number of inferred VegetarianPizzas: " + inferredSubclasses.size()); 

    // Print out the inferred subclasses 
    System.out.println("VegetarianPizzas:"); 
    for (Iterator it = inferredSubclasses.iterator(); it.hasNext();) { 
        OWLNamedClass curClass = (OWLNamedClass) it.next(); 
        System.out.println(curClass.getName()); 
    } 
}
Updating Protégé-OWL with Inferred Information

Some of the methods on ProtegeOWLReasoner query the external DIG reasoner to obtain inferred information and then insert this information into the OWLModel. To some extent this can be useful for large models, because rather than querying the reasoner for information about every class in the ontology manually (each time incurring the cost of an HTTP request/response), a 'bulk' query is performed - once for consistency checking, once for inferred superclass checking, and once for equivalent class checking. After these bulk queries have been performed, the OWLModel is updated, which means that the model can be examined "offline" from the reasoner. An example of this is shown below. The classifyTaxonomy method bulk queries the reasoner for the consistency, inferred superclasses, and equivalent classes of every class in the ontology (using only 3 HTTP request/responses) and then inserts this information into the Protégé-OWL model. The model can then be queried for the stored inferred information.
// We can classify the whole ontology, which will put the 
// inferred class hierarchy information directly into the Protégé-OWL model.
System.out.println("Classifying taxonomy..."); 
reasoner.classifyTaxonomy(null); 
System.out.println("...Classified taxonomy!"); 

// We can then use the methods on OWLNamedClass for getting inferred
// information, without having to make separate queries to the external 
// DIG reasoner. 
System.out.println("Inferred subclasses of VegetarianPizza:"); 
inferredSubclasses = vegetarianPizza.getInferredSubclasses(); 
for (Iterator it = inferredSubclasses.iterator(); it.hasNext();) { 
    OWLNamedClass curClass = (OWLNamedClass) it.next(); 
    System.out.println(curClass.getName()); 
}
Examples of other methods that update the OWLModel are computeInconsistentClasses, which queries the reasoner for the consistency of all classes in the ontology and the updates the OWLModel. Also, the computeInferredTypes method queries the reasoner for the inferred types of all individuals in the ontology and then updates the OWLModel.

Putting it all Together

The steps from above have been concatenated and shown as a complete example below. The source code can also be downloaded from this Web page. In order to compile and run the example code, you need to make certain that the JAR files for the Protégé application folder and the JAR files for the Protégé-OWL editor folder (plugins/edu.stanford.smi.protegex.owl) are on your classpath.
import edu.stanford.smi.protegex.owl.model.OWLModel; 
import edu.stanford.smi.protegex.owl.model.OWLNamedClass; 
import edu.stanford.smi.protegex.owl.ProtegeOWL; 
import edu.stanford.smi.protegex.owl.inference.protegeowl.ReasonerManager; 
import edu.stanford.smi.protegex.owl.inference.protegeowl.ProtegeOWLReasoner; 
import edu.stanford.smi.protegex.owl.inference.dig.reasoner.DIGReasonerIdentity; 
 
import java.util.Iterator; 
import java.util.Collection; 
 
/** 
 * The Univeristy Of Manchester
 * Medical Informatics Group
 * Date: Jan 7, 2005 
 */
public class ReasonerExample { 

    public static void main(String[] args) { 
        try { 
            final String ONTOLOGY_URL = "http://www.co-ode.org/ontologies/pizza/pizza_20041007.owl"; 
            final String REASONER_URL = "http://localhost:8080"; 
 
            // Load the ontology from the specified URL 
            OWLModel model = ProtegeOWL.createJenaOWLModelFromURI(ONTOLOGY_URL); 
 
            // Get the reasoner manager and obtain a reasoner for the OWL model. 
            ReasonerManager reasonerManager = ReasonerManager.getInstance(); 
            ProtegeOWLReasoner reasoner = reasonerManager.getReasoner(model); 
 
            // Set the reasoner URL and test the connection 
            reasoner.setURL(REASONER_URL); 
            if(reasoner.isConnected()) { 
                // Get the reasoner identity - this contains information
                // about the reasoner, such as it's name and version,
                // and the tell and ask operations that it supports.
                DIGReasonerIdentity reasonerIdentity = reasoner.getIdentity(); 
                System.out.println("Connected to " + reasonerIdentity.getName()); 
 
                // Get the VegetarianPizza OWLNamedClass from the OWLModel 
                OWLNamedClass vegetarianPizza = model.getOWLNamedClass("VegetarianPizza"); 
                if(vegetarianPizza != null) { 
                    // Get the number of asserted subclasses of VegetarianPizza 
                    Collection assertedSubclasses = vegetarianPizza.getNamedSubclasses(); 
                    System.out.println("Number of asserted VegetarianPizzas: " + assertedSubclasses.size()); 
 
                    // Now get the inferred subclasses of VegetarianPizza 
                    Collection inferredSubclasses = reasoner.getSubclasses(vegetarianPizza, null); 
                    System.out.println("Number of inferred VegetarianPizzas: " + inferredSubclasses.size()); 
                    System.out.println("VegetarianPizzas:"); 
                    for(Iterator it = inferredSubclasses.iterator(); it.hasNext();) { 
                        OWLNamedClass curClass = (OWLNamedClass) it.next(); 
                        System.out.println(curClass.getName()); 
                    } 
 
                    // We can classify the whole ontology, which will put the
                    // inferred class hierarchy information directly into the Protégé-OWL model. 
                    System.out.println("Classifying taxonomy..."); 
                    reasoner.classifyTaxonomy(null); 
                    System.out.println("...Classified taxonomy!"); 

                    // We can then use the methods on OWLNamedClass for getting inferred
                    // information, without having to make separate queries to the external
                    // DIG reasoner, as this information is now in the OWLModel. 
                    System.out.println("Inferred subclasses of VegetarianPizza:"); 
                    inferredSubclasses = vegetarianPizza.getInferredSubclasses(); 
                    for(Iterator it = inferredSubclasses.iterator(); it.hasNext();) { 
                        OWLNamedClass curClass = (OWLNamedClass) it.next(); 
                        System.out.println(curClass.getName()); 
                    } 
                } 
                else { 
                    System.out.println("Could not find VegetarianPizza"); 
                } 
            } 
            else { 
                System.out.println("Reasoner not connected!"); 
            } 
        } 
        catch(Exception e) { 
            e.printStackTrace(); 
        } 
    } 
}
Example output from the program above looks as follows:
Connected to Racer
Number of asserted VegetarianPizzas: 0
Number of inferred VegetarianPizzas: 10
VegetarianPizzas:
Caprina
QuattroFormaggi
Fiorentina
Giardiniera
Margherita
Soho
Veneziana
Mushroom
PrinceCarlo
Rosa
Classifying taxonomy...
...Classified taxonomy!
Inferred subclasses of VegetarianPizza:
Margherita
QuattroFormaggi
PrinceCarlo
Mushroom
Soho
Giardiniera
Rosa
Veneziana
Caprina
Fiorentina
OWL-Full Models

Description Logic reasoners can only work with ontologies that fall into the OWL-DL species. However, with the Protégé-OWL reasoner API, this does not mean that it is impossible to use a reasoner with an OWL-Full model. The API attempts to strip out the OWL-Full elements when it tells (describes) the ontology to the reasoner. This means that it is possoble to reason about the "DL core" of an ontology. When the API strips out OWL-Full elements it produces warnings, which are logged using the ReasonerLogger. An example of how to listen for and print out log messages is shown below:
ReasonerLoggerListener lsnr = new ReasonerLoggerListener() { 
public void logRecordPosted(ReasonerLogRecord reasonerLogRecord) { 
    if (reasonerLogRecord instanceof MessageLogRecord) { 
        MessageLogRecord msgLog = (MessageLogRecord) reasonerLogRecord; 
        System.out.println(msgLog.getMessage()); 
    } 
} }; 
ReasonerLogger.getInstance().addListener(lsnr);
Summary

The Protégé-OWL reasoning API was developed for Protégé-OWL as part of the CO-ODE project in collaboration with Stanford Medical Informatics. Questions, comments, and bug reports should be posted on the protege-owl mailing list.



HOME |  OVERVIEW |  DOCUMENTATION |  DOWNLOADS |  SUPPORT |  COMMUNITY |  WIKI |  ABOUT US
Valid XHTML 1.0! Valid CSS!