Exploiting alignments and reasoning: advanced tutorial on the Alignment API and server

This version:
https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/
Author:
Jérôme Euzenat, INRIA & Univ. Grenoble Alpes

Here is a more advanced tutorial for the alignment API which explains how to interface the API with other components. This tutorial will show how to:

Whenever possible, we try to provide the answers through REST, in command-line, Java programs (and later Alignment server interface).

Other tutorials are available.

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 1.3.8, IDDL (now DRAon) 1.4 and LogMap 2.

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

$ export CLASSPATH=../../../lib/align.jar:../../../lib/procalign.jar:../../../lib/jena/jena.jar:../../../lib/jena/arq.jar:../../../lib/iddl/iddl.jar:../../../lib/hermit/hermit.jar:../../../lib/ontosim/ontosim.jar:../../../lib/slf4j/slf4j-api.jar:../../../lib/slf4j/jcl-over-slf4j.jar:../../../lib/slf4j/log4j-over-slf4j.jar:../../../lib/xerces/xercesImpl.jar:../../../lib/jena/iri.jar:../../../lib/jena/httpcore.jar:results
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 -cp $CLASSPATH -d results Skeleton.java

This programme can be run by:

$ java -cp $CLASSPATH:Skeleton Skeleton
It provides no output for the moment.

Matching ontologies

This can be achieved:

by finding an alignment from the web/server

After introducing the main variables:

RESTSERV=http://aserv.inrialpes.fr/rest U1=https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl U2=https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl CWD=`pwd`

$ curl -L -H "Accept:application/rdf+xml" ${RESTSERV}'/find?onto1='${U1}'&onto2='${U2}
resulting in something like:
<findResponse xml:base='http://exmo.inrialpes.fr/align/service#' xmlns='http://exmo.inrialpes.fr/align/service#'> <id>274</id> <sender>http://aserv.inrialpes.fr</sender> <alignmentList> <alid>http://aserv.inrialpes.fr/alid/1417700303045/7849</alid> </alignmentList> </findResponse>
which can always been retrieved in RDF/XML by
$ curl -L -H "Accept:application/rdf+xml" http://aserv.inrialpes.fr/alid/1417700303045/7849

After introducing the main variables:

String RESTServ = "http://aserv.inrialpes.fr/rest/"; 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"; 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);

After introducing the main variables:

using a matcher on the alignment server

Write a program that does try to find an alignment on the alignment server https://aserv.inrialpes.fr and, if none is found, computes one.

After introducing the main variables:

$ curl -L -H "Accept:application/rdf+xml" ${RESTSERV}'/match?method=fr.inrialpes.exmo.align.impl.method.StringDistAlignment&stringFunction=smoaDistance&noinst=1&onto1='${U1}'&onto2='${U2}
returning the URL:

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 ); }

After introducing the main variables:

by running a matcher locally

$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.Procalign -i fr.inrialpes.exmo.align.impl.method.StringDistAlignment -DstringFunction=smoaDistance -Dnoinst=1 https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl
or:
$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.Procalign -i fr.inrialpes.exmo.align.impl.method.StringDistAlignment -DstringFunction=smoaDistance -Dnoinst=1 file:ontology1.owl file:ontology2.owl

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; }

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)


Merge ontologies and test consistency

Generating an OWL ontology merging the two ontologies

Generating OWL axioms from the alignments and merge the ontologies can be done with the alignment API support.

Considering that the alignment has been stored in a file: alignment.rdf, this can be obtained locally:

$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.ParserPrinter file:alignment.rdf -r fr.inrialpes.exmo.align.impl.renderer.OWLAxiomsRendererVisitor -o results/alignment.owl
or from the server:
$ curl -L -H "Accept:application/rdf+xml" ${RESTSERV}'/retrieve?method=fr.inrialpes.exmo.align.impl.renderer.OWLAxiomsRendererVisitor&id=http://aserv.inrialpes.fr/alid/1417700303045/7849' > results/alignment.owl

In fact everything is done in one step:

// (Sol1) generate a merged ontology between the ontologies (OWLAxioms) File merged = File.createTempFile( "MyApp-results",".owl"); PrintWriter writer = new PrintWriter ( new FileWriter( merged, false ), true ); AlignmentVisitor renderer = new OWLAxiomsRendererVisitor(writer); al.render(renderer); writer.flush(); writer.close();

You can look at the result in results/alignment.owl.

Not ready yet


Testing ontology consistency with HermiT

Considering that the merged ontologies in a file: results/alignment.owl, and that you have downloaded HermiT (the Command line version of hermit requires gnu getopt which is not shipped anymore with the Alignment API):

$ java -jar HermiT.jar results/alignment.owl -U

which displays

Exception in thread "main" org.semanticweb.owlapi.reasoner.InconsistentOntologyException: Inconsistent ontology at org.semanticweb.HermiT.Reasoner.throwInconsistentOntologyExceptionIfNecessary(Unknown Source) at org.semanticweb.HermiT.Reasoner.checkPreConditions(Unknown Source) at org.semanticweb.HermiT.Reasoner.isSatisfiable(Unknown Source) at org.semanticweb.HermiT.cli.CommandLine$SatisfiabilityAction.run(Unknown Source) at org.semanticweb.HermiT.cli.CommandLine.main(Unknown Source)

Create Reasoner instance and load the merged ontologies:

OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); // Load the ontology OWLOntology ontology = manager.loadOntology( IRI.create( "file:"+merged.getPath() ) ); OWLReasoner reasoner = new Reasoner( ontology );

Test consistency:

// Test consistency if ( reasoner.isConsistent() ) { System.out.println( " *** The aligned ontologies are consistent" ); } else { System.out.println( " *** The aligned ontologies are inconsistent" ); return; }

It is even possible to test the satisfiability of classes:

// Test coherence for ( OWLClass cl : ontology.getClassesInSignature( true ) ) { if ( !reasoner.isSatisfiable( cl ) ) { System.out.println( cl+" is incoherent" ); } }

Load the two ontologies and the alignment in the IDDL reasoner:

ArrayList allist = new ArrayList(); allist.add( al ); IDDLReasoner dreasoner = new IDDLReasoner( allist, Semantics.DL );

Test consistency and check if a particular correspondence is a consequence:

if ( dreasoner.isConsistent() ) { System.out.println( "IDDL: the alignment network is consistent"); } else { System.out.println( "IDDL: the alignment network is inconsistent"); }

Repairing an alignment with Alcomo or LogMap repair

Assuming that LogMap has been downloaded (it takes directly the Alignment format as input):

$ java -jar logmap2_standalone.jar DEBUGGER https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl RDF alignment.rdf $CWD/results false false
this displays the following output:
Loading ontologies... IRI: https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl IRI: https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl ...Done Read RDF Align mapping objects: 11 Num original mappings: 11 Error keeping mappings... Num repaired mappings: 10 TOTAL REPAIR TIME (s): 0.505
The result can be found in results/mappings_repaired_with_LogMap.rdf. It contains only 10 of the initial correspondences.
Unfortunately, LogMap outputs wrong alignments (two occurence of ontology1 in the header must be replaced by ontology2). Once this fixed, it is possible to perform again:
$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.ParserPrinter file:results/mappings_repaired_with_LogMap.rdf -r fr.inrialpes.exmo.align.impl.renderer.OWLAxiomsRendererVisitor -o results/alignment.owl $ java -jar HermiT.jar results/alignment.owl -U

yielding

Classes equivalent to 'owl:Nothing': owl:Nothing
java -jar AgreementMakerLightCLI.jar -r -s ontology1.owl -t ontology2.owl -i alignment.rdf -o results/aml-alignment.rdf

This also assumes that Alcomo has been downloaded and is added to the path.

Settings.BLACKBOX_REASONER = Settings.BlackBoxReasoner.HERMIT; IOntology sourceOnt = new IOntology( "ontology1.owl" ); IOntology targetOnt = new IOntology( "ontology2.owl" ); Mapping mapping = new Mapping( "alignment.rdf"); // Find the optimal repair ExtractionProblem ep = new ExtractionProblem( ExtractionProblem.ENTITIES_CONCEPTSPROPERTIES, ExtractionProblem.METHOD_OPTIMAL, ExtractionProblem.REASONING_COMPLETE ); ep.bindSourceOntology( sourceOnt ); ep.bindTargetOntology( targetOnt ); ep.bindMapping( mapping ); ep.init(); ep.solve(); System.out.println("Num discarded correspondences using Alcomo: " + (mapping.size() - ep.getExtractedMapping().size())); MappingWriterXml alcomoWriter = new MappingWriterXml(); alcomoWriter.writeMapping( "results/alcomo-alignment.rdf", ep.getExtractedMapping() );
Should display:
Num dicarded correspondences using Alcomo: 1
and have saved the result in results/alcomo-alignment.rdf.
OWLOntology onto1 = manager.loadOntology(IRI.create("https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl")); OWLOntology onto2 = manager.loadOntology(IRI.create("https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl")); MappingsReaderManager readermanager = new MappingsReaderManager( "alignment.rdf", "RDF"); Set&ly;MappingObjectStr> input_mappings = readermanager.getMappingObjects(); LogMap2_RepairFacility logmap2_repair = new LogMap2_RepairFacility( onto1, onto2, input_mappings, false, false); //Set of mappings repaired by LogMap Set<MappingObjectStr> repaired_mappings = logmap2_repair.getCleanMappings();
Should return similar output as the command line.

Testing subsumption

It is now possible to check that the newly generated alignment is consistent. Hence we can check some entailment results.

Considering that the merged ontologies in a file: results/alignment.owl, and that you have uploaded HermiT (the Command line version of hermit requires gnu getopt which is not shipped anymore with the Alignment API):

$ java -jar HermiT.jar results/alignment.owl -s https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante -e https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante

which displays

All sub-classes of 'https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante': owl:Nothing <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#TutorEstudiante> Classes equivalent to '<https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante>': <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante> <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student>
and
$ java -jar HermiT.jar results/alignment.owl -s https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student -e https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student

which displays

All sub-classes of 'https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student': owl:Nothing <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#TutorEstudiante> Classes equivalent to '<https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student>': <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante> <https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Student>

Create Reasoner instance and load the merged ontologies as before and perform some subsumption tests:

testOWLReasonerSubClass( manager, reasoner, estud, person ); testOWLReasonerSubClass( manager, reasoner, estud, student );

Such that:

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) ); } }
The answer should be:
OWLReasoner(Merged): Estudiante is not necessarily subclass of Person OWLReasoner(Merged): Estudiante is subclass of Student

Check if a particular correspondence is a consequence:

testIDDLSubClass( dreasoner, uri1, uri2, estud, person ); testIDDLSubClass( dreasoner, uri1, uri2, estud, student );

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 result should be:
IDDL: Estudiante <= Person is not entailed IDDL: Estudiante <= Student is entailed

SPARQL querying with an alignment

Our final goal is to get that list of students. For that purpose, several strategies may be adopted:

Let explore them.

Instance reasoning

Starting from where we were with the HermiT reasonner, it is possible to retrive the instances of "Estudiantes" and to manipulate them:

// get the instances of a class OWLClass estud = manager.getOWLDataFactory().getOWLClass( IRI.create( "https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#Estudiante" ) ); OWLClass person = manager.getOWLDataFactory().getOWLClass( IRI.create( "https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#Person" ) ); OWLClass student = manager.getOWLDataFactory().getOWLClass( IRI.create( "https://moex.gitlabpages.inria.fr/alignapi/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)+")");
This should output:
OWLReasoner(Merged): There are 47 students (Estudiante)

Transforming queries

The following solutions use the query in the file query.sparql which is expressed with respect to ontology1.owl.

The query can be transformed on command line through:
$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.TransformQuery -a file:alignment.rdf -q query.sparql -Donto2=https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl# -o results/query2.sparql $ cp ontology2.owl results/ontology2.rdf # because arq does not owl as input $ java -cp $CLASSPATH arq.query --query results/query2.sparql --data results/ontology2.rdf
The result will be:
-------------------------------------------------------------------------------------------------------------- | fn | ln | t | s | ============================================================================================================== | "Archie" | "Shepp" | "Occarina University" | | | "Sonny" | "Rollins" | "Universita di Miggliore" | "M. Pecorino" | | "Astrud" | "Gilberto" | "Universität der Gemütlichkeit" | "Pr. Dr. M. Coppa" | | "Peggy" | "Lee" | "University des Mitteleuropa" | "a.Univ.Prof.DI.Dr. Z. Melone" | | "Glenn" | "Miller" | "University of Shepperington" | "Professor G. Limone" | | "Rickie Lee" | "Jones" | "Philip Vanderbilt Universiteit" | "A. Lambretta" | | "Rickie Lee" | "Jones" | "Velo Research" | "A. Lambretta" | | "Lionel" | "Hampton" | "Politecnico di Madalena" | "O. Mascarponne" | | "Lionel" | "Hampton" | "Politecnico di Madalena" | "A. Gorgonzola" | | "Eleonore" | "Rigby" | "Politecnico di Bermudas" | | | "Diana" | "Krall" | "Royal University of Worchester sauce" | "Dr. A. Verdura" | | "Diana" | "Krall" | "Royal University of Worchester sauce" | "C. Fragola" | | "Dave" | "Brubeck" | "University of Namibia" | "P. Tiramissu" | | "Dave" | "Brubeck" | "University of Namibia" | "G. Belladonna" | | "Milt" | "Jackson" | "Escena" | | | "Julian" | "Aldderley" | "Politecnico di Madalena" | | | "Betty" | "Sinclair" | "Institute for Social Coworkers" | | | "Cilla" | "Black" | "University of Shepperington" | "Prof. G. Limone" | | "Natalie" | "Merchant" | "JOHANNISBEER RESEARCH" | | | "Django" | "Reinhardt" | "IRIA Saskatchevan" | "Prof. Chr. Melocoton" | | "Django" | "Reinhardt" | "University Pie XXIII" | "Prof. Chr. Melocoton" | | "Ray" | "Bryant" | "Handshuh University" | | | "Jackie" | "McLean" | "Polytechnic of Madeira" | "S. Zucchini" | | "Art" | "Tatum" | "National Kapodistrian University of Athens" | "B. Tiramisu" | | "Duke" | "Ellington" | "Vanilla University of Technology" | "Prof. G. Cetriolo" | | "Chick" | "Corea" | "University of Ausblick" | "Prof. Dr. A. Belladonna" | | "Kenny" | "Burrell" | "Politecnico di Belladona" | "S. Proscuitto" | | "Joe" | "Zawinul" | "Institute for Social Coworkers" | | | "Dexter" | "Gordon" | "Eelberg University" | "C. Pannacotta" | --------------------------------------------------------------------------------------------------------------

This can be achieved by using Jena ARQ query evaluator:

Model model = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_MEM_RULE_INF, null ); // Load ontology 1 model.read( "file:ontology1.owl" ); // Query in ontology 1 QueryExecution qe = QueryExecutionFactory.create( QueryFactory.read( "file:query.sparql" ), model ); ResultSet results = qe.execSelect(); // Output query results ResultSetFormatter.out(System.out, results, query); // Load ontology 2 model = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_MEM_RULE_INF, null ); model.read( "file:ontology2.owl" ); // Transform query String transformedQuery = null; try { InputStream in = new FileInputStream( "query.sparql" ); BufferedReader reader = new BufferedReader( new InputStreamReader(in) ); String line = null; String queryString = ""; while ((line = reader.readLine()) != null) { queryString += line + "\n"; } Properties parameters = new Properties(); transformedQuery = ((BasicAlignment)al).rewriteQuery( queryString, parameters ); } catch ( Exception ex ) { ex.printStackTrace(); } // Query ontology 2 displayQueryAnswer( model, QueryFactory.create( transformedQuery ) ); qe = QueryExecutionFactory.create( QueryFactory.create( transformedQuery ), model ); results = qe.execSelect(); // Output query results ResultSetFormatter.out(System.out, results, query);
This gives the result:
------------------------------------------------------------------------------------------------------- | 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" | | "Laurent" | "De Wilde" | "University of Sussex" | "Ugo Calamari" | | "Laurent" | "De Wilde" | "University of Sussex" | "Simona Riccota" | | "Charlie" | "Parker" | "Institut Von Humboldt" | "Cecilia Parmiggiano" | | "Carmen" | "McRae" | "University of the Rainforest" | "Mario Staggioni" | | "Benny" | "Goodman" | "The Univesity of the true way" | "Prof. Dr. Riccardo Peperoni" | | "Thelonious" | "Monk" | "Madeira Instutute of Technology" | "Stefano Zucchini" | | "Ella" | "Fitzgerald" | "Vanilla University of Technology" | "Prof. Giancarlo Cetriolo" | | "Janis" | "Joplin" | "University of Zoulouland" | "Fiorenta Pescadore" | | "Janis" | "Joplin" | "University of Zoulouland" | "Medusa Pesto" | | "Bud" | "Powell" | "Cogebom" | "Giovanni Dolomitti" | | "Bud" | "Powell" | "SPAM" | "Giovanni Dolomitti" | | "John" | "Coltrane" | "Estrellas" | | | "Aretha" | "Franklin" | "University of Huelva" | | | "Carla" | "Bley" | "none" | "Christina Melocoton" | | "Cab" | "Calloway" | "University of Shepperington" | | | "Stan" | "Getz" | "Altacola research centre" | "Prof. Pierpaolo Polenta" | | "Art" | "Blackey" | "University of Albatra" | "Pierluiggi Pomodoro" | | "Art" | "Blackey" | "University of Albatra" | "Paola Pomodoro" | | "Nina" | "Simone" | "Research Center of the Americas" | "Domenica Melanzana" | | "Ornette" | "Coleman" | "Trinidad College Dubrovnik" | "Carla Cipolla" | | "Billie" | "Holliday" | "University of Soupaloignon" | "Mr. Laurenzo Girafiore" | | "Billie" | "Holliday" | "University of Soupaloignon" | "Dr.Federico diGuava" | | "Oscar" | "Peterson" | "Institute for Applied Boxology" | "Dott. Antolio Bresaola" | | "Coleman" | "Hawkins" | "University of South Poland" | "Pepe Frutti di Mare" | | "John" | "Zorn" | "Altacola research centre" | "Prof. Pierpaolo Polenta" | ------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------- | fn | ln | t | s | ============================================================================================================== | "Archie" | "Shepp" | "Occarina University" | | | "Sonny" | "Rollins" | "Universita di Miggliore" | "M. Pecorino" | | "Astrud" | "Gilberto" | "Universität der Gemütlichkeit" | "Pr. Dr. M. Coppa" | | "Peggy" | "Lee" | "University des Mitteleuropa" | "a.Univ.Prof.DI.Dr. Z. Melone" | | "Glenn" | "Miller" | "University of Shepperington" | "Professor G. Limone" | | "Rickie Lee" | "Jones" | "Philip Vanderbilt Universiteit" | "A. Lambretta" | | "Rickie Lee" | "Jones" | "Velo Research" | "A. Lambretta" | | "Lionel" | "Hampton" | "Politecnico di Madalena" | "O. Mascarponne" | | "Lionel" | "Hampton" | "Politecnico di Madalena" | "A. Gorgonzola" | | "Eleonore" | "Rigby" | "Politecnico di Bermudas" | | | "Diana" | "Krall" | "Royal University of Worchester sauce" | "Dr. A. Verdura" | | "Diana" | "Krall" | "Royal University of Worchester sauce" | "C. Fragola" | | "Dave" | "Brubeck" | "University of Namibia" | "P. Tiramissu" | | "Dave" | "Brubeck" | "University of Namibia" | "G. Belladonna" | | "Milt" | "Jackson" | "Escena" | | | "Julian" | "Aldderley" | "Politecnico di Madalena" | | | "Betty" | "Sinclair" | "Institute for Social Coworkers" | | | "Cilla" | "Black" | "University of Shepperington" | "Prof. G. Limone" | | "Natalie" | "Merchant" | "JOHANNISBEER RESEARCH" | | | "Django" | "Reinhardt" | "IRIA Saskatchevan" | "Prof. Chr. Melocoton" | | "Django" | "Reinhardt" | "University Pie XXIII" | "Prof. Chr. Melocoton" | | "Ray" | "Bryant" | "Handshuh University" | | | "Jackie" | "McLean" | "Polytechnic of Madeira" | "S. Zucchini" | | "Art" | "Tatum" | "National Kapodistrian University of Athens" | "B. Tiramisu" | | "Duke" | "Ellington" | "Vanilla University of Technology" | "Prof. G. Cetriolo" | | "Chick" | "Corea" | "University of Ausblick" | "Prof. Dr. A. Belladonna" | | "Kenny" | "Burrell" | "Politecnico di Belladona" | "S. Proscuitto" | | "Joe" | "Zawinul" | "Institute for Social Coworkers" | | | "Dexter" | "Gordon" | "Eelberg University" | "C. Pannacotta" | --------------------------------------------------------------------------------------------------------------
There are indeed 47 individuals (but more occurences in the table due to multiple supervisors).

Querying with the merged ontology

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.

This does not work, either in command line or in Java, though it has worked in the past. Apparently, Jena does not properly load the imported ontologies. Anyone knowing the solution will be

$ cp results/alignment.owl results/alignment.rdf $ java -cp $CLASSPATH arq.query --query query.sparql --data results/alignment.rdf
Which give the result: (INCORRECT)
------------------- | fn | ln | t | s | =================== -------------------

Load the merged ontology under Jena:

// (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:"+merged.getPath() ); in.close();

Read the query (please play by changing the query)

// Create a new query Query query = QueryFactory.read( "file:query.sparql" );

Evaluation:

// 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);
The results for this evaluation is: (SHOULD BE)
--------------------------------------------------------------------------------------- | 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" | ...

Generating SPARQL constructs

A SPARQL construct query may be use for extracting data expressed in one ontology and generate this data with respect to the other ontology. It is possible to generate such constructs from

$ java -cp $CLASSPATH fr.inrialpes.exmo.align.cli.ParserPrinter file:alignment.rdf -r fr.inrialpes.exmo.align.impl.renderer.SPARQLConstructRendererVisitor
which generates a set of queries containing at least this:
PREFIX ns1:<https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology2.owl#> PREFIX ns0:<https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/ontology1.owl#> PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#> CONSTRUCT { ?s rdf:type ns0:Estudiante . } WHERE { ?s rdf:type ns1:Student . } CONSTRUCT { ?s ns0:supervisor ?o . } WHERE { ?s ns1:phd-advisor ?o . } [...] CONSTRUCT { ?s rdf:type ns0:Tutor . } WHERE { ?s rdf:type ns1:Professor . } [...] CONSTRUCT { ?s ns0:lastname ?o . } WHERE { ?s ns1:name ?o . } [...] CONSTRUCT { ?s ns0:year ?o . } WHERE { ?s ns1:year-in-phd ?o . } PREFIX rdf: CONSTRUCT { ?s ns0:country ?o . } WHERE { ?s ns1:country-of-study ?o . } CONSTRUCT { ?s ns0:gender ?o . } WHERE { ?s ns1:gender ?o . } CONSTRUCT { ?s ns0:firstname ?o . } WHERE { ?s ns1:first-name ?o . } CONSTRUCT { ?s ns0:city ?o . } WHERE { ?s ns1:city-of-study ?o . } CONSTRUCT { ?s ns0:topic ?o . } WHERE { ?s ns1:topics-of-interest ?o . } CONSTRUCT { ?s ns0:affiliation ?o . } WHERE { ?s ns1:institution ?o . }
These queries may be applied to the entries of ontology2.owl and generates triples using ontology1.

Full solution

Do you want to see a possible solution?

A full working solution is MyApp.java which can be activated by:

$ javac -cp $CLASSPATH -d results MyApp.java $ java -cp $CLASSPATH:results MyApp

This is without the recourse to LogMap. The (two) LogMap parts may be uncommented from the code and the instructions above run again with logmap2_standalone.jar in the classpath.

Further exercises

More info: https://moex.gitlabpages.inria.fr/alignapi/tutorial/


https://moex.gitlabpages.inria.fr/alignapi/tutorial/tutorial4/