3

How to get Least Common Subsumer(LCS) of individuals in ontology using SPARQL Query? (I want to get common concept of two individuals. Here i have mentioned owl file code)

<!DOCTYPE rdf:RDF [
    <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
    <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
    <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
    <!ENTITY ace_lexicon "http://attempto.ifi.uzh.ch/ace_lexicon#" >
    <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>

<rdf:RDF xmlns="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#"
     xml:base="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:ace_lexicon="http://attempto.ifi.uzh.ch/ace_lexicon#">
    <owl:Ontology rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8"/>

    <owl:AnnotationProperty rdf:about="&ace_lexicon;CN_pl"/>

    <owl:AnnotationProperty rdf:about="&ace_lexicon;CN_sg"/>

    <owl:AnnotationProperty rdf:about="&ace_lexicon;PN_sg"/>

    <owl:Class rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#BollwormsPests_Pesticide">
        <rdfs:subClassOf rdf:resource="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Pesticide"/>
        <ace_lexicon:CN_pl>Bollworms_Pesticides</ace_lexicon:CN_pl>
        <ace_lexicon:CN_sg>Bollworms_Pesticide</ace_lexicon:CN_sg>
    </owl:Class>

    <owl:Class rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Carbamate">
        <rdfs:subClassOf rdf:resource="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#BollwormsPests_Pesticide"/>
        <ace_lexicon:CN_pl>Carbamates</ace_lexicon:CN_pl>
        <ace_lexicon:CN_sg>Carbamate</ace_lexicon:CN_sg>
    </owl:Class>

    <owl:Class rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Organophosphates">
        <rdfs:subClassOf rdf:resource="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#BollwormsPests_Pesticide"/>
        <ace_lexicon:CN_pl>Organophosphateses</ace_lexicon:CN_pl>
        <ace_lexicon:CN_sg>Organophosphates</ace_lexicon:CN_sg>
    </owl:Class>

    <owl:Class rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Pesticide">
        <ace_lexicon:CN_pl>Pesticides</ace_lexicon:CN_pl>
        <ace_lexicon:CN_sg>Pesticide</ace_lexicon:CN_sg>
    </owl:Class>

    <owl:NamedIndividual rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Carbaryl">
        <rdf:type rdf:resource="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Carbamate"/>
        <ace_lexicon:PN_sg>Carbaryl</ace_lexicon:PN_sg>
    </owl:NamedIndividual>

    <owl:NamedIndividual rdf:about="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Ethion">
        <rdf:type rdf:resource="http://www.semanticweb.org/chetan/ontologies/2014/5/untitled-ontology-8#Organophosphates"/>
        <ace_lexicon:PN_sg>Ethion</ace_lexicon:PN_sg>
    </owl:NamedIndividual>
</rdf:RDF>

Answer must be here BollwormsPests_Pesticide:

My Java code is :

package sparql;

import com.hp.hpl.jena.iri.impl.Main;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.sparql.syntax.*;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SPARQLReasoningQuery {

    public static void main(String args[]) throws FileNotFoundException, IOException {

        BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\Chetan\\Desktop\\Final Cotton Ontology\\query.txt"));
        String sparqlQuery;
        String[] finalStringArray = new String[2];
        String subString[];
        int i = 0;
        try {
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();

            while (line != null) {
                sb.append(line);
                sb.append("\n");
                line = br.readLine();
            }
            sparqlQuery = sb.toString();
        } finally {
            br.close();
        }
        subString = sparqlQuery.split("\n", 2);

        Pattern pattern = Pattern.compile("\\?(\\w+)");
        Matcher matcher = pattern.matcher(subString[0]);

        while (matcher.find()) {
            finalStringArray[i] = matcher.group(1);
            i++;
        }
        sparqlTest(sparqlQuery, finalStringArray);
    }

    public static void sparqlTest(String sparqlQuery, String[] param) {
        FileManager.get().addLocatorClassLoader(Main.class.getClassLoader());
        Model model = FileManager.get().loadModel("C:\\Users\\Chetan\\Desktop\\Final Cotton Ontology\\CottonCropOntology.owl");
        Reasoner reasoner = ReasonerRegistry.getOWLReasoner().bindSchema(model);
        InfModel infmodel = ModelFactory.createInfModel(reasoner, model);
        String queryString = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> "
                + "PREFIX owl: <http://www.w3.org/2002/07/owl#> "
                + "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> "
                + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
                + "PREFIX : <http://www.owl-ontologies.com/Ontology1359542935.owl#> " + sparqlQuery;
        Query query = QueryFactory.create(queryString);
        QueryExecution qexec = QueryExecutionFactory.create(queryString, infmodel);
        System.out.println("\t\t" + param[0] + "\t\t\t\t\t\t\t\t\t" +((param[1] != null)?param[1]:""));
        try {
            ResultSet results = qexec.execSelect();
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                Resource r = soln.getResource(param[0]);
                System.out.print(r);
                if (param[1] != null) {
                    Literal name = soln.getLiteral(param[1]);
                    System.out.print("\t" + name.getString());
                }
                System.out.println();
            }
        } finally {
            qexec.close();
        }
    }
}

I use following query as taylor suggested me:

select ?lcs where {
  ?lcs ^rdf:type :Carbaryl, :Ethion ;
       a owl:Class .
  filter not exists { 
    ?llcs ^rdf:type :Carbaryl, :Ethion ;
          a owl:Class ;
          rdfs:subClassOf+ ?lcs .
  }
}

Still getting blank in answer

Chetan
  • 63
  • 1
  • 8
  • possible duplicate of [finding common superclass and length of path in class hierarchies](http://stackoverflow.com/questions/19680440/finding-common-superclass-and-length-of-path-in-class-hierarchies) – Joshua Taylor May 07 '14 at 11:46

1 Answers1

3

This may be a duplicate of finding common superclass and length of path in class hierarchies, but that question doesn't have an accepted answer, and is also asking about path length, which makes things more complicated. In general, you can find common superclasses of classes ?subclass1 and ?subclass2 with:

?subclass1 rdfs:subClassOf* ?superclass .
?subclass2 rdfs:subClassOf* ?superclass .

You can make that shorter with:

?superclass ^rdfs:subClassOf* ?subclass1, ?subclass2 .

That will find all common superclasses of the two subclasses. There may not be a single most specific common superclass, but you can find those that are as specific as possible by asking for only those superclasses that are not subclasses of any other superclass:

?superclass ^rdfs:subClassOf* ?subclass1, ?subclass2 .
filter not exists { 
  ?moreSpecificSuperclass rdfs:subClassOf ?superclass ;
                          ^rdfs:subClassOf* ?subclass1, ?subclass2 .
}

To find the LCS of some particular instances, you'd need to do something like this:

?instance1 rdf:type/rdfs:subClassOf* ?lcs .
?instance2 rdf:type/rdfs:subClassOf* ?lcs .
filter not exists {
  ?instance1 rdf:type/rdfs:subClassOf* ?sublcs .
  ?instance2 rdf:type/rdfs:subClassOf* ?sublcs .
  ?sublcs rdfs:subClassOf ?lcs .
}

As before, you can shorten that bit to:

?lcs ^(rdf:type/rdfs:subClassOf*) ?instance1, ?instance2 .
filter not exists {
  ?sublcs ^(rdf:type/rdfs:subClassOf*) ?instance1, ?instance2 ;
          rdfs:subClassOf ?lcs . 
}

The first line ensures that ?type is a common type of ?x and ?y, and the filter expression ensures that there's no subclass of ?type that is also a common type of ?x and ?y.

Here's a minimal example that shows that this approach works. Here's an ontology with the class hierarchy:

owl:Thing
  A
    B
      C {c}
      D {d}
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="https://stackoverflow.com/q/23510851/1281433/lcs#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
  <owl:Ontology rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs"/>
  <owl:Class rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#A"/>
  <owl:Class rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#B">
    <rdfs:subClassOf rdf:resource="https://stackoverflow.com/q/23510851/1281433/lcs#A"/>
  </owl:Class>
  <owl:Class rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#C">
    <rdfs:subClassOf rdf:resource="https://stackoverflow.com/q/23510851/1281433/lcs#B"/>
  </owl:Class>
  <owl:Class rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#D">
    <rdfs:subClassOf rdf:resource="https://stackoverflow.com/q/23510851/1281433/lcs#B"/>
  </owl:Class>
  <owl:NamedIndividual rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#c">
    <rdf:type rdf:resource="https://stackoverflow.com/q/23510851/1281433/lcs#C"/>
  </owl:NamedIndividual>
  <owl:NamedIndividual rdf:about="https://stackoverflow.com/q/23510851/1281433/lcs#d">
    <rdf:type rdf:resource="https://stackoverflow.com/q/23510851/1281433/lcs#D"/>
  </owl:NamedIndividual>
</rdf:RDF>

The individuals c and d are elements of the classes C and D, respectively. The LCS is B. Here's the query and its results:

prefix :      <https://stackoverflow.com/q/23510851/1281433/lcs#> 
prefix owl:   <http://www.w3.org/2002/07/owl#>
prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#>

select ?lcs where {
  ?lcs ^(rdf:type/rdfs:subClassOf*) :c, :d ;
       a owl:Class .
  filter not exists { 
    ?llcs ^(rdf:type/rdfs:subClassOf*) :c, :d ;
          a owl:Class ;
          rdfs:subClassOf+ ?lcs .
  }
}
-------
| lcs |
=======
| :B  |
-------
Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • It is important that you can create a minimal example. Start from scratch and create an ontology that contains just enough information to test your query. Then, edit your question and add the ontology to it. – Joshua Taylor Jun 23 '14 at 19:40
  • I saw your ontology. I queried on it through my java code. I am getting blank answer. Even i also tested it through protege's sparql engine. I also got blank answer. In my thesis i am using apache jena. – Chetan Jun 23 '14 at 20:25
  • 1) I help on Stack Overflow for free because it benefits everyone. If you don't post your code and data in your question, then it doesn't really benefit anyone else but you. If you insist on communication that's not on Stack Overflow, it might be possible to discuss consulting fees. 2) I *did* look at the dropbox link that you sent me, and the query in your query.text is not analogous to the last update I made to my answer. When I run *my query* with the appropriate `:` prefix and `:Carbaryl` and `:Ethion` instead of `:c` and `:d` on your data, I get the result `:BollwormPests_Pesticides`. – Joshua Taylor Jun 23 '14 at 20:49
  • I made changes according to your query select ?lcs where { ?lcs ^rdf:type :Carbaryl, :Ethion ; a owl:Class . filter not exists { ?llcs ^rdf:type :Carbaryl, :Ethion ; a owl:Class ; rdfs:subClassOf+ ?lcs . } } stil getting blank in answer – Chetan Jun 24 '14 at 10:04
  • Jena's command line `sparql` tool, included with the distribution. E.g., `sparql --query query.text --data ontology.owl`. It's the quickest way to run a query, and it uses the same Jena API that we have access to. Use the command line tools to debug your query. Then if you have problems with your code, you can ask a question like "this query works on the command line and produces these results, but this code that runs the same query doesn't." That's part of creating [a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – Joshua Taylor Jun 24 '14 at 11:52
  • whem i am using jena's command line sparql i got following error Line 3, column 12: Unresolved prefixed name: rdf:type – Chetan Jun 24 '14 at 15:09
  • @Chetan That makes sense; the rdf: prefix isn't declared in the query (my mistake). You'll need to add it. It's easy to see what it's supposed to be from the RDF/XML namespace declaration. – Joshua Taylor Jun 24 '14 at 15:43
  • @taylor thank you . I got output. But i need to understand some concepts from you. 1) why i need to add (/rdfs:subClassOf*). Without it i am not getting result. here we are dealing with individual then rdf:type is only not sufficient why? 2) why i need to add + after subClassOf. Without '+' i also getting result. – Chetan Jun 24 '14 at 17:37
  • If you only have `a rdf:type A. A rdfs:subClassOf B.`, you don't have `a rdf:type B`, unless you also have a reasoner, and it sounds like you don't. However, you *do* have `a rdf:type/rdfs:subClassOf* B`. That's why you need the property paths. As to what the particular paths mean, they're described very clearly in the standard, see [9 Property Paths](http://www.w3.org/TR/sparql11-query/#propertypaths). – Joshua Taylor Jun 24 '14 at 21:28
  • I want to use reasoner in my sparql query. I am using Jena's command line argument. How can i use reasoner so i get inference from ontology. i am using cmd code: sparql --data=OWL file name --query=query.text – Chetan Jun 30 '14 at 11:19
  • "I am using Jena's command line argument." In this question, you provided Java code, which means that your question about reasoners with Jena's command line tools is really a *different* question. It's probably better asked on the Jena mailing list, but I expect the answer is that the command line tools don't use the reasoners. You'll probably need to use code for that (or set up a Fuseki instance with some inference models, etc.). – Joshua Taylor Jun 30 '14 at 13:33
  • So i can't get the inference using Jena's command line 'sparql' tool? – Chetan Jun 30 '14 at 13:42
  • Not that I'm aware of, but then again, I don't know everything about Jena. There's a reason that I said this would be better asked as a separate question. Other people who might know the answer would probably see the question, but they won't see this thread of comments. – Joshua Taylor Jun 30 '14 at 14:53