Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Exploiting alignments and reasoning</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<link rel="stylesheet" type="text/css" href="../../base.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" />
<script type="text/javascript">
<!--
function show(id) {
var element = document.getElementById(id);
element.style.display = "block";
}
function hide(id) {
var element = document.getElementById(id);
element.style.display = "none";
}
-->
</script>
<style type="text/css">
<!--
div.logic {
padding-left: 5px;
padding-right: 5px;
margin-top: 10px;
margin-bottom: 10px;
}
-->
</style>
</head>
<body style="background-color: #FFFFFF;">
<h1>Exploiting alignments and reasoning: advanced tutorial on the Alignment <abbr title="Application Programming Interface">API</abbr> and server</h1>
<p>
<dl>
<dt>This version:</dt>
<dd>http://alignapi.gforge.inria.fr/tutorial/tutorial4/</dd>
<dt>Author:</dt>
<dd><a href="http://exmo.inrialpes.fr/people/euzenat">Jérôme Euzenat</a>, INRIA & LIG
</dd>
</dl>
</p>
<p style="border-top: 2px solid
#AAAAAA; padding-top: 15px; padding-bottom: 15px;">
Here is a more advanced tutorial for the
alignment <abbr>API</abbr> which explains how to interface the API
with other components.
This tutorial will show how to:
<ul>
<li>communicate the alignment server
through its REST web service API,</li>
<li>manipulate alignments with the Alignment API in Java,</li>
<li>perform OWL reasoning on aligned ontologies and compose
alignments.</li>
</ul>
This time, the tutorial is based on Java programming and using various
related APIs.
</p>
<p>
Other tutorials are <a href="../index.html">available</a>.</p>
<p style="border-top: 2px solid #AAAAAA;"><small>This tutorial has
been designed for the Alignment API version 4.0. It is currently
incomplete due to the upgrade of Pellet to version 2.1 and IDDL.</small></p>
<h2>Preparation</h2>
<p>Just:
<div class="fragment">
</div>
</p>
<h2>Data</h2>
<p>
We have two ontologies, <a href="ontology1.owl">ontology1.owl</a>
and <a href="ontology2.owl">ontology2.owl</a>, under which two sets of
students are described. Unfortunately, the
administration started to record participants with their own ontology
before finding that using <a href="http://foaf-project.org">FOAF</a>
would be a better idea. We now end up with two incomplete lists of
participants.
</p>
<p>
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.
</p>
<p>For that purpose, you have to develop a program in Java.
We first define the CLASSPATH because a lot of external software is required
<div class="fragment">
$ setenv CLASSPATH ../../../lib/align.jar:../../../lib/procalign.jar:../../../lib/jena/jena.jar:../../../lib/jena/arq.jar:../../../lib/iddl/iddl.jar:../../../lib/pellet/pellet-core.jar:../../../lib/pellet/pellet-owlapiv3.jar:../../../lib/pellet/pellet-rules.jar:../../../lib/pellet/pellet-datatypes.jar:../../../lib/pellet/aterm-java-1.6.jar:../../../lib/pellet/pellet-query.jar:../../../lib/ontosim/ontosim.jar:../../../lib/pellet/pellet-el.jar:../../../lib/log4j/commons-logging.jar:../../../lib/log4j/log4j.jar:../../../lib/xerces/xercesImpl.jar:../../../lib/jena/iri.jar:../../../lib/jena/icu4j_3_4.jar:../../../lib/jena/concurrent.jar:../../../lib/xsdlib/relaxngDatatype.jar:../../../lib/xsdlib/xsdlib.jar:results
</div>
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:
<div class="fragment">
$ javac -d results Skeleton.java
<p>This programme can be run by:
$ java Skeleton
</div>
It provides no output for the moment.
</p>
<h2>Matching ontologies</h2>
<p>
This can be achieved:
<ul>
<li>by finding an alignment from the web/server</li>
<li>by running a matcher locally</li>
<li>by running a matcher on the alignment server</li>
<li>by finding a chain of alignments from the web/server</li>
</ul>
</p>
<p>
Write a program that does try to find an alignment on the alignment
server <a href="http://aserv.inrialpes.fr">http://aserv.inrialpes.fr</a>
and, if none is found, computes one.
</p>
<div class="button">
<input type="button" onclick="show('qu0')" value="Various variables"/>
<input type="button" onclick="show('qu1')" value="Show solution 1"/>
<input type="button" onclick="show('qu2')" value="Show solution 2"/>
<input type="button" onclick="show('qu3')" value="Show solution 3"/>
<input type="button" onclick="hide('qu0');hide('qu1');hide('qu2');hide('qu3');" value="Hide solutions"/>
</div>
<div class="explain" id="qu0">
<p>After introducing the main variables:</p>
<pre>
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(); }
</pre>
</div>
<div class="explain" id="qu1">
<p>The programme will invoke the alignment server:</p>
<pre>
// (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 );
</pre>
<p>Retrieve the alignment itself:</p>
<pre>
// retrieve it
// If there exists alignments, ask for the first one
NodeList alset = extractFromResult( found, "//findResponse/alignmentList/alid[1]/text()", false );
</pre>
<p>And parse it:</p>
<pre>
// parse it as an alignment
AlignmentParser aparser = new AlignmentParser(0);
Alignment alu = aparser.parseString( xmlString );
al = ObjectAlignment.toObjectAlignment((URIAlignment)alu);
<div class="explain" id="qu2">
<p>Just create an instance of AlignmentProcess and call it:</p>
// (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;
}
</pre>
</div>
<div class="explain" id="qu3"><p>Match on the server:</p>
<pre>
// (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 );
}
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
</pre>
<p>The remainder is the same as in the first solution.</p>
</div>
<div class="logic">
<p><b>More work:</b> You can also store localy computed alignments on
the alignment server.</p>
</div>
<div class="button">
<input type="button" onclick="show('qu4')" value="Show solution"/>
<input type="button" onclick="hide('qu4');" value="Hide solution"/>
</div>
<div class="explain" id="qu4"><p>Not ready yet (but not difficult)</p>
<pre>
</pre>
</div>
<h2>Manipulate the data</h2>
<p>
Again, this is either:
<ul>
<li>generating OWL axioms from the alignments and merge the ontologies</li>
<li>transforming data from one ontology to another</li>
</ul>
</p>
<p>
This can be done with the alignment API support.
</p>
<div class="button">
<input type="button" onclick="show('qu5')" value="Show solution 1"/>
<!--input type="button" onclick="show('qu6')" value="Show solution 2"/-->
<input type="button" onclick="hide('qu5');hide('qu6');" value="Hide solutions"/>
</div>
<div class="explain" id="qu5">
<p>In fact everything is done in one step:</p>
<pre>
// (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();
<p>You can look at the result in <a href="results/myresult.owl">results/myresult.owl</a>.</p>
</div>
<div class="explain" id="qu6"><p>Not ready yet</p>
<pre>
</pre>
</div>
<h2>Generate the answers</h2>
<p>
This can be done in three ways:
<ul>
<li>using SPARQL</li>
<li>using a reasonner such as Pellet to answer these queries against
the merged ontologies.</li>
<li>using a "distributed" reasoner, in our case IDDL, to answer these
queries against non merged aligned ontologies.</li>
</ul>
</p>
<p>
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.
</p>
For using Pellet, which is not bundled with the Alignment API, it will be necessary
to <a href="http://clarkparsia.com/pellet/download">download
it</a> and add in
the classpath the corresponding aterm-java-1.6.jar, pellet-core.jar, pellet-rules.jar,
pellet-datatypes.jar, pellet-jena.jar, pellet-query.jar, pellet-owlapiv3.jar and pellet-el.jar jar-files
which are not shipped with the Alignment API.
</p>
</p>
<div class="button">
<input type="button" onclick="show('qu7')" value="Show solution 1"/>
<input type="button" onclick="show('qu8')" value="Show solution 2"/>
<!--input type="button" onclick="show('qu9')" value="Show solution 3"/-->
<input type="button" onclick="hide('qu7');hide('qu8');hide('qu9');" value="Hide solutions"/>
</div>
<div class="explain" id="qu7">
<p>Prepare the system:</p>
<pre>
// (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();
</pre>
<p>Query (please play by changing the query)</p>
<pre>
// Create a new query
String queryString =
"PREFIX foaf: <http://xmlns.com/foaf/0.1/> " +
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
"PREFIX aa: <http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology1.owl#> " +
"SELECT ?fn ?ln ?t ?s " +
" ?student rdf:type aa:Estudiante . " +
" ?student aa:firstname ?fn. " +
" ?student aa:lastname ?ln. " +
"OPTIONAL { ?student aa:affiliation ?t . } " +
"OPTIONAL { ?student aa:supervisor ?s . } " +
Query query = QueryFactory.create(queryString);
// Execute the query and obtain results
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();
// Output query results
ResultSetFormatter.out(System.out, results, query);
</pre>
</div>
<div class="explain" id="qu8">
<p>Create Reasoner instance and load the merged ontologies:</p>
<pre>
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
// Load the ontology
OWLOntology ontology = manager.loadOntology( IRI.create( "file:"+tempOntoFileName ) );
OWLReasoner reasoner = new PelletReasoner( ontology, org.semanticweb.owlapi.reasoner.BufferingMode.NON_BUFFERING );
reasoner.prepareReasoner();
</pre>
<p>Get the instances of "Estudiantes":</p>
<pre>
// 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("Pellet(Merged): There are "+instances.size()+" students "+clname(estud));
</pre>
<p>Some subsumption tests:</p>
<pre>
testPelletSubClass( manager, reasoner, estud, person );
testPelletSubClass( manager, reasoner, estud, student );
private String clname( OWLClassExpression cl ) {
return cl.asOWLClass().getIRI().getFragment();
}
public void testPelletSubClass( OWLOntologyManager manager, OWLReasoner reasoner, OWLClassExpression d1, OWLClassExpression d2 ) {
OWLAxiom axiom = manager.getOWLDataFactory().getOWLSubClassOfAxiom( d1, d2 );
if ( reasoner.isEntailed( axiom ) ) {
System.out.println( "Pellet(Merged): "+clname(d1)+" is subclass of "+clname(d2) );
} else {
System.out.println( "Pellet(Merged): "+clname(d1)+" is not necessarily subclass of "+clname(d2) );
}
}
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
</pre>
</div>
<div class="explain" id="qu9">
<p>Load the two ontologies and the alignment in the IDDL reasoner:</p>
<pre>
IDDLReasoner dreasoner = new IDDLReasoner( Semantics.DL );
dreasoner.addOntology( uri1 );
dreasoner.addOntology( uri2 );
dreasoner.addAlignment( al );
</pre>
<p>Test consistency and check if a particular correspondence is a consequence:</p>
<pre>
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");
}
</pre>
<p>Such that:</p>
<pre>
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" );
}
}
</pre>
</div>
The results for these execution are, for SPARQL:
<pre>
---------------------------------------------------------------------------------------
| 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" |
...
</pre>
for Pellet:
Pellet(Merged): There are 47 students http://alignapi.gforge.inria.fr/tutorial/tutorial4/ontology1.owl#Estudiante
Pellet(Merged): Estudiante is not necessarily subclass of Person
Pellet(Merged): Estudiante is subclass of Student
</pre>
and for IDDL:
<pre>
IDDL: the alignment network is consistent
IDDL: Estudiante <= Person is not entailed
IDDL: Estudiante <= Student is entailed
</pre>
<h2>Full solution</h2>
<p>Do you want to see a possible solution?</p>
<p>A full working solution is <a href="MyApp.java">MyApp.java</a>.</p>
<p style="text-align: center;">http://alignapi.gforge.inria.fr/tutorial/tutorial4/</p>
</small>
<hr />
<p>$Id$</p>
</body>
</html>