Exploiting alignments and reasoning

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

This version:
  http://alignapi.gforge.inria.fr/tutorial/tutorial2/
Author:
  Jérôme Euzenat, INRIA & LIG

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:

- communicate the alignment server through its REST web service API,
- manipulate alignments with the Alignment API in Java,
- perform OWL reasoning on aligned ontologies and compose alignments.

This time, the tutorial is based on Java programming and using various related APIs.

Other tutorials are available.

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.0.2 and IDDL.

## Preparation

Just:

$ cd tutorial2

## 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

$ 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
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 MyApp.java

This programme can be run by:

$ java MyApp
You can start with the empty template Skeleton.java.

## 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 = "JETest";
    	Alignment al = null;
    	URI uri1 = null;
    	URI uri2 = null;
    	//String u1 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl";
    	//String u2 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl";
    	String u1 = "file:ontology1.owl";
    	String u2 = "file:ontology2.owl";
    	String method = "fr.inrialpes.exmo.align.impl.method.StringDistAlignment";
    	String tempOntoFileName = "/tmp/myresult.owl";
    	Parameters 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
    	// (better passing to the SAXHandler)
    	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.setParameter("stringFunction","smoaDistance");
    	    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&force=true", 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)
    	File merged = new File( tempOntoFileName );
    	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 myresult.owl

Not ready yet

## Generate the answers

This can be done in three ways:

- using SPARQL
- using a reasonner such as Pellet 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 runing 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 );
    	//OntModelSpec.OWL_MEM_RDFS_INF or no arguments to see the difference...
    	Model model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF,null);
    	model.read(in,"file:///tmp/myresult.owl");
    	in.close();

Query (please play by changing the query)

            // Create a new query
    	String queryString =
    		"PREFIX foaf:  " +
    		"PREFIX rdf:  " +
    		"PREFIX aa:  " +
    		"SELECT ?fn ?ln ?t " +
    		"WHERE {" +
                    "      ?student rdf:type aa:Person . " +
    		"      ?student aa:firstname  ?fn. " +
    		"      ?student aa:lastname  ?ln. " +
    		"      ?student aa:topic ?t . " +
    		"      }";

Evaluation:

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

Create Reasoner instance and load the merged ontologies:

    	OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
    	Reasoner reasoner = new Reasoner( manager );
    	try {
    	    OWLOntology ontology = manager.loadOntology( URI.create( "file://"+tempOntoFileName ) );
    	    reasoner.loadOntology( ontology );
    	} catch (OWLOntologyCreationException ooce) { ooce.printStackTrace(); }

Get the instances of "Estudiantes":

    	OWLClass estud = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#Estudiante" ) );
    	OWLClass person = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Person" ) );
    	OWLClass student = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Student" ) );
    	Set instances  = reasoner.getIndividuals( estud, false );
    	System.err.println("Pellet(Merged): There are "+instances.size()+" students "+estud.getURI());

Some subsumption tests:

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

Such that:

        public void testPelletSubClass( OWLOntologyManager manager, Reasoner reasoner, OWLDescription d1, OWLDescription d2 ) {
    	OWLAxiom axiom = manager.getOWLDataFactory().getOWLSubClassAxiom( d1, d2 );
    	boolean isit = reasoner.isEntailed( axiom );
    	if ( isit ) {
    	    System.out.println( "Pellet(Merged): "+d1+" is subclass of "+d2 );
    	} else {
    	    System.out.println( "Pellet(Merged): "+d1+" is not necessarily subclass of "+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 Pellet):

    Pellet(Merged): There are 47 students http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#Estudiante
    Pellet(Merged): Estudiante is not necessarily subclass of Person
    Pellet(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

http://alignapi.gforge.inria.fr/tutorial/tutorial2/

$Id: index.html 1402 2010-03-31 08:43:56Z euzenat $