Configuring Pellet Reasoner and Jena

How to configure Pellet Reasoner with Jena


What this blog is about

This blog is purely about how to implement a reasoner in your semantic web application. Hence, I assume you're familiar with the concept of the semantic web and its standards. I also assume you're familiar with the concept of reasoners. Not to worry if you're not, I would briefly introduce reasoners and ultimately show you through some code snippets how to implement a reasoner in your semantic web application. I assume you're in the process of developing a semantic web app or are interested in developing one.

Reasoners

Reasoners provide a means of making inferences from facts depicted as triples in your semantic web application. This allows your application infer new facts i.e new triple assertions in your model. In other words, implicit facts or entailments are deduced from the explicit facts in your triple store each time new explicit facts are added. For instance if we have the following facts:
Properties and Relationships
isFatherOf type ObjectProperty isSonOf type ObjectProperty isFatherOf inversePropertyOf isSonOf Instances
Mike isSonOf David
Above, I've simply defined properties isFatherOf and isSonOf, indicating that an inverse relationship exists between both properties so that if we explicitly declare that "Mike isSonOf David", we can implicitly infer from the inverse relationship between isSonOf and isFatherOf that David isFatherOf Mike. Of course in reality it's sometime more complex but this instance best depicts the concept of reasoning.
Reasoners are vital when designing applications across separate datasets like in mashups. An example could be a mashup from two separate datasets say Freebase and eventful to create an application that allows users search for artists of a particular genre, era, style while mapping that to concert dates and locations from eventful. You can see Emmanuelle Della Valle's detailed video tutorial at the International Semantic Web Conference (ISWC) for such an application. Reasoners could be:
  • Internal - Reasoners built into the Jena framework i.e Jena's reasoners. These reasoners have varying inference levels depending on the functionalities you want. OWLReasoner will provide OWLConstructs like sameAs, minCardinality. Again the Jena API documents the inference levels.
  • External Reasoners - Reasoners like Pellet.
  • External Reasoners - Remotely offered via the DIG interface.The interface defines a simple protocol (based on HTTP PUT/GET) along with an XML Schema that describes a concept language and accompanying operations.
Ideally, your application should have:

  • Separate datasets in RDF format, otherwise there are numerous ways of converting from relational database models or excel format data to RDF. In this case, Freebase and Eventful.
  • Ontologies which describe the domains of interest thereby introducing the notion of semantics to the model.
  • Allignment statements which would bridge both datasets
  • This tutorial assumes you're using Jena semantic web framework. Jena comes with several reasoners and supports the ability to interface with third party reasoners like Pellet. Pellet is an open source OWL DL reasoning engine developed in Java. It has considerable community support.

Code Snippets
Reasoning can only occur on an existing model and so I will show how the model is created, populated and finally how reasoning is carried out using Jena's inferencing engine and Pellet.

Stage 1: Create your model. Jena Model interface defines a class containing reference to a set of triples. Each model type supports varying inference levels i.e (RDF, RDFS, OWL). Models are created with a factory method called ModelFactory.

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

public class SemanticApp
{
//member variables (private or protected)
... 

//methods
//Creates an empty default model with default specification in memory.
public static Model createDefaultModel()
{
Model model = ModelFactory.createOntologyModel();
RDFReader g = model.getReader();
g.setProperty("error-mode", "lax" );
return model;
}
Since the next stage would involve populating the model, I prefer using the RDFReader returned by calling the model's getReader() method. I can also say:
...
model.read(...);
But in my experience, RDFReader allows you set a number of properties as well as enhance the error handling capabilities which comes in handy when dealing with large RDF files created from templates or sources you're unfamiliar with as there are bound to be errors or encoding issues. In this case, I have set the error-mode to "lax".

Stage 2: Creating the Ontology Model
Your application might require a number of ontologies. Remember I said earlier that Jena deals with models and there are many types of models. Here we will create an ontology model which we will then populate with the ontologies we intend to work with.

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
...
...
public static OntModel createOntologyModel()
{
OntModel ontologyModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM);
return ontologyModel; 
}
The ontology model created above is a memory based Ontology model. The argument OntModelSpec.OWL_DL_MEM tells the engine to create an ontology model according to a particular specification which in this case is an OWL DL model stored in memory with no additional entailment reasoning. This is because we will be implementing the Pellet third party inferencer. OntModelSpec class provides other options. You can look through the java documentation for more information. Populate the ontology model with your ontologies. Remember to specify the namespace of your ontology.
public static OntModel createOntologyModel()
{
String ontNamespace = "http://myNamespace.com";
String ontologyFile = "D:\\MYONTOLOGY\\onto.owl#");
//Inputstream that loads the ontology from a directory on my computer
InputStream ont = FileManager.get().open(ontologyFile);
//load the ontology
ontologyModel.read(ont,ontNamespace);
ont.close();
...

}

Stage 3: Integrating the Reasoner
Using Jena's built inferencer we will use ReasonerRegistry to get the reasoner of our choice.

...
/**
*Return a prebuilt simplified configuration for the default RDFS reasoner
*Use this if you're creating an RDFS Reasoner
*/
Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
/**
*Prebuilt standard configuration for the default OWL reasoner.
*Use this if you're creating an OWL Reasoner
*/
Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
//bind the reasoner to the ontology model
reasoner = reasoner.bindSchema(ontologyModel);
//Bind the reasoner to the data model into a new Inferred model
Model infModel = ModelFactory.createInfModel(reasoner,model);
}
Note that a reasoner can be bound to more than one model. The beauty of this is that with more than one model the reasoner can infer across different models and vocabularies. The final part is to then map the reasoner model to the data model created earlier. What we get back is a new inferred model with new entailments i.e inferred data thanks to the inferencing and reasoning undertaken by the inferencer. This new inferred model is still pure RDF and can be queryed and navigated using the API just like you will do with normal RDF.
Now using Pellet, we call PelletReasonerFactory which is a factory method that creates reasoners for us.
Reasoner reasoner = PelletReasonerFactory.theInstance().create();
Bind the reasoner object created by PelletReasonerFactory to the ontology and then create the new inferred model like we did previously.

Next time I will show you how to query semantic datasets like OrdnanceSurvey or data.gov for your applicatioins or mashups.

2 comments:

  1. Excellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking. stufe a pellet

    ReplyDelete