Search code examples
rdfsparql

How to CONSTRUCT a property's transitive closure in SPARQL?


I have an RDF/XML dataset, and it has some relations that can be built into some inference rules. I built my inference rules using SPARQL in Jena API. For example, there is a part_of relation, if termA is part_of termB , and termB is part_of termC, so we can infer that termA is part_of termC. But I need to make this rule work recursively, so I want all the triples inferred from this rule to be let say the input dataset again then be checked using this rule. To infer new triples I used construct in SPARQL:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX go: <http://www.geneontology.org/dtds/go.dtd#>
CONSTRUCT {?termA go:part_of ?termC}
WHERE {
  ?termA go:part_of ?termB .
  ?termB go:part_of ?termC .
  FILTER (?termA != ?termC) .
}

from this query above, I can infer only the two level of part_of relation, but what I need is the multilevel one. So I tried to make a subquery like this, using the syntax shown in slide 9 of Marianne Shaw's Ontology Views Update, which in turn might be based on Simon Schenk's A SPARQL Semantics Based on Datalog:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX go: <http://www.geneontology.org/dtds/go.dtd#>
CONSTRUCT {?termA go:part_of ?termC}
FROM <A:/workspace_luna/RDFQuery/src/test.rdf>
FROM NAMED ?g <CONSTRUCT {?termA go:part_of ?termC}
               FROM <A:/workspace_luna/RDFQuery/src/test.rdf>
               WHERE {
                 ?termA go:part_of ?termB .
                 ?termB go:part_of ?termC .
                 FILTER (?termA != ?termC) .
               }>
WHERE {
  ?termA go:part_of ?termB .
  ?termB go:part_of ?termC .
  FILTER (?termA != ?termC) .
}

But I obtained an error. I've looked around in many sources and also I tried to apply to my queries, but no one works. Is there any other way to do this?


Solution

  • Problems in your code

    So I tried to make subquery like this: …

    I'm not sure what subquery syntax you're trying to use, but it's not legal. Subqueries are just wrapped in braces. E.g.,

    select ?s where {
      { select ?x where { ... } }
    }
    

    The query you've written isn't legal.

    But I obtained an error.

    If you don't show us the error, we certainly can't help in fixing it. I expect that you got a syntax error. You can validate your query using sparql.org's query validator. That probably won't help too much in this case, though, because you can only use select queries in subqueries. (It would be very helpful, though, if construct queries were supported for subqueries.)

    Transitive closures for construct queries

    In general, you can't do arbitrary recursion in SPARQL. However, in the specific case that you've got, you can use property paths in the pattern to construct the transitive closure of a pattern. E.g.,

    construct { ?a :partOf ?b }
    where { ?a :partOf+ ?b }
    

    This says that if there's a path of non-zero length from ?a to ?c using just :partOf links, then include a triple ?a :partOf ?b in the constructed output.