This tutorial has been initially designed for the Alignment API 4.0 using Jena, Pellet and IDDL.
It has been reengineered in the Alignment API 4.5 to use Jena, HermiT and IDDL 1.4.
Preparation
Just:
$ cd tutorial4
Data
We have two ontologies, ontology1.owl
and ontology2.owl, under which two sets of
students are described. Unfortunately, the
administration started to record participants with their own ontology
before finding that using FOAF
would be a better idea. We now end up with two incomplete lists of
participants.
The goal is to have a unified view of these participants. For that
purpose, we will match the two ontologies and reason with the result
in order to view participants from boths ontologies under the other
ontology. This is not a difficult task, the goal here is only to show
how this could be achieved.
For that purpose, you have to develop a program in Java.
We first define the CLASSPATH because a lot of external software is required
The list of jars is long, but at least it is explicit and you
should be safe with this one.
This programme can be compiled by:
$ javac -d results Skeleton.java
This programme can be run by:
$ java Skeleton
It provides no output for the moment.
Matching ontologies
This can be achieved:
by finding an alignment from the web/server
by running a matcher locally
by running a matcher on the alignment server
by finding a chain of alignments from the web/server
Write a program that does try to find an alignment on the alignment
server http://aserv.inrialpes.fr
and, if none is found, computes one.
After introducing the main variables:
String myId = "Test";
Alignment al = null;
URI uri1 = null;
URI uri2 = null;
String u1 = "file:ontology1.owl";
String u2 = "file:ontology2.owl";
String method = "fr.inrialpes.exmo.align.impl.method.StringDistAlignment";
String tempOntoFileName = "results/myresult.owl";
Properties params = new BasicParameters();
try {
uri1 = new URI( u1 );
uri2 = new URI( u2 );
} catch (URISyntaxException use) { use.printStackTrace(); }
The programme will invoke the alignment server:
// (Sol1) Try to find an alignment between two ontologies from the server
// ask for it
String found = getFromURLString( RESTServ+"find?onto1="+u1+"&onto2="+u2, false );
Retrieve the alignment itself:
// retrieve it
// If there exists alignments, ask for the first one
NodeList alset = extractFromResult( found, "//findResponse/alignmentList/alid[1]/text()", false );
And parse it:
// parse it as an alignment
AlignmentParser aparser = new AlignmentParser(0);
Alignment alu = aparser.parseString( xmlString );
al = ObjectAlignment.toObjectAlignment((URIAlignment)alu);
Just create an instance of AlignmentProcess and call it:
// (Sol2) Match the ontologies with a local algorithm
if ( al == null ){ // Unfortunatelly no alignment was available
AlignmentProcess ap = new StringDistAlignment();
ap.init( uri1, uri2 );
params.setProperty("stringFunction","smoaDistance");
params.setProperty("noinst","1");
ap.align( (Alignment)null, params );
al = ap;
}
Match on the server:
// (Sol3) Match the ontologies on the server
if ( alset.getLength() == 0 ) {
// call for matching
String match = getFromURLString( RESTServ+"match?onto1="+u1+"&onto2="+u2+"&method="+method+"&pretty="+myId+"&action=Match", true );
}
The remainder is the same as in the first solution.
More work: You can also store localy computed alignments on
the alignment server.
Not ready yet (but not difficult)
Manipulate the data
Again, this is either:
generating OWL axioms from the alignments and merge the ontologies
transforming data from one ontology to another
This can be done with the alignment API support.
In fact everything is done in one step:
// (Sol1) generate a merged ontology between the ontologies (OWLAxioms)
PrintWriter writer = null;
File merged = new File( tempOntoFileName );
writer = new PrintWriter ( new FileWriter( merged, false ), true );
AlignmentVisitor renderer = new OWLAxiomsRendererVisitor(writer);
al.render(renderer);
writer.flush();
writer.close();
using an OWLReasoner such as HermiT to answer these queries against
the merged ontologies.
using a "distributed" reasoner, in our case IDDL, to answer these
queries against non merged aligned ontologies.
In case you go for SPARQL please, take care of the inference regime
and observe what are the differences in this case. You can of course
run various queries and start by running them in one of the initial
ontologies instead of the merged one.
Prepare the system:
// (Sol1) Use SPARQL to answer queries (at the data level)
InputStream in = new FileInputStream( merged );
Model model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF,null);
model.read( in, "file:"+tempOntoFileName );
in.close();
// get the instances of a class
OWLClass estud = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology1.owl#Estudiante" ) );
OWLClass person = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology2.owl#Person" ) );
OWLClass student = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology2.owl#Student" ) );
Set<OWLNamedIndividual> instances = reasoner.getInstances( estud, false ).getFlattened();
System.err.println("OWLReasoner(Merged): There are "+instances.size()+" students "+clname(estud));
private String clname( OWLClassExpression cl ) {
return cl.asOWLClass().getIRI().getFragment();
}
public void testOWLReasonerSubClass( OWLOntologyManager manager, OWLReasoner reasoner, OWLClassExpression d1, OWLClassExpression d2 ) {
OWLAxiom axiom = manager.getOWLDataFactory().getOWLSubClassOfAxiom( d1, d2 );
if ( reasoner.isEntailed( axiom ) ) {
System.out.println( "OWLReasoner(Merged): "+clname(d1)+" is subclass of "+clname(d2) );
} else {
System.out.println( "OWLReasoner(Merged): "+clname(d1)+" is not necessarily subclass of "+clname(d2) );
}
}
Load the two ontologies and the alignment in the IDDL reasoner:
IDDLReasoner dreasoner = new IDDLReasoner( Semantics.DL );
dreasoner.addOntology( uri1 );
dreasoner.addOntology( uri2 );
dreasoner.addAlignment( al );
Test consistency and check if a particular correspondence is a consequence:
if ( dreasoner.isConsistent() ) {
System.out.println( "IDDL: the alignment network is consistent");
testIDDLSubClass( dreasoner, uri1, uri2, estud, person );
testIDDLSubClass( dreasoner, uri1, uri2, estud, student );
} else {
System.out.println( "IDDL: the alignment network is inconsistent");
}
Such that:
public void testIDDLSubClass( IDDLReasoner dreasoner, URI onto1, URI onto2, OWLDescription d1, OWLDescription d2 ) {
Alignment al2 = new ObjectAlignment();
try {
al2.init( onto1, onto2 );
// add the cell
al2.addAlignCell( d1, d2, "<", 1. );
} catch (AlignmentException ae) { ae.printStackTrace(); }
if ( dreasoner.isEntailed( al2 ) ) {
System.out.println( "IDDL: "+d1+" <= "+d2+" is entailed" );
} else {
System.out.println( "IDDL: "+d1+" <= "+d2+" is not entailed" );
}
}
The results for these execution are, for SPARQL:
---------------------------------------------------------------------------------------
| fn | ln | t | s |
=======================================================================================
| "Miles" | "Davis" | "JOHANNISBEER RESEARCH" | "Univ.-Prof. Dr. Paolo Carciofo" |
| "Chet" | "Baker" | "University Pie XXIII" | |
| "McCoy" | "Tyner" | "University of Soupaloignon" | "Dr Nanni Girasole" |
...
for OWLReasoner:
OWLReasoner(Merged): There are 47 students http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology1.owl#Estudiante
OWLReasoner(Merged): Estudiante is not necessarily subclass of Person
OWLReasoner(Merged): Estudiante is subclass of Student
and for IDDL:
IDDL: the alignment network is consistent
IDDL: Estudiante <= Person is not entailed
IDDL: Estudiante <= Student is entailed