3

I am trying to write a query on a class with a restriction defined on it, that will determine whether the restriction has been satisfied and, if it has, return it.

An example class is defined as follows:

:ThingB  a            owl:Class ;
    rdfs:subClassOf   :ThingA ;
    rdfs:subClassOf   [ a                  owl:Restriction ;
                        owl:allValuesFrom  [ a                   owl:Class ;
                                             owl:intersectionOf  ( :ThingC :ThingD )
                                           ] ;
                        owl:onProperty     owl:isConfirmedBy
                      ] ;
    rdfs:subClassOf   [ a                   owl:Restriction ;
                        owl:onProperty      owl:isConfirmedBy ;
                        owl:someValuesFrom  [ a            owl:Class ;
                                              owl:unionOf  ( :ThingE :ThingF :ThingG :ThingH )
                                            ]
                      ] .

I would like to be able to write a query that says if I have both ThingC and ThingD and any one of ThingE, ThingF, ThingG or ThingH then return ThingB.

The following query will do the first part i.e. return ThingB only if I have both ThingC and ThingD:

SELECT 
*
WHERE
{
    ?thing rdfs:subClassOf ?restriction .
    ?restriction (owl:allValuesFrom | owl:someValuesFrom)/(owl:intersectionOf | owl:unionOf) ?list .

    FILTER NOT EXISTS { 
        ?list rdf:rest*/rdf:first ?things.
        FILTER( !(?things in (:ThingC, :ThingD )) )
    }
}

How would I include the second part of the restriction that says there must also be at least one of ThingE, ThingF, ThingG or ThingH for this to return a match on ThingB?

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
bakersman
  • 68
  • 5
  • I'm so intrigued by this. Could I have your ontology to give it a go, please? The ontologies I have none had this condition so my efforts didn't result in anything! – Artemis Mar 03 '15 at 09:49
  • @Artemis thanks for the reply but I can't supply our ontology to you. Hopefully the example I've given above is detailed enough for you to be able to replicate the problem in your own ontology. – bakersman Mar 03 '15 at 10:31
  • are you trying to validate your abox wrt to your tbox? – Michael Mar 03 '15 at 13:15
  • @Michael I have to admit I don't fully understand your question as I'm very new to ontologies and SPARQL. From what I've just briefly read about the terms abox and tbox I think what I am asking could be succinctly described as you have stated but I'm not sure. In my simpler terms , I've defined restrictions on my classes and I want to be able to run a query that will return any classes whose restrictions have been satisfied by a set of input values. – bakersman Mar 03 '15 at 14:21
  • Person is an example of a class, these are in your tbox. You could state that "All people must have one and only one age" -- that's the kind of restriction you're thinking of, yes? And if there is an individual "Michael" (in your abox) you want to find out whether or not they have an age, and thus, whether or not the restriction(s) are "satisified". That is, check that your abox is valid wrt to your tbox. Right? – Michael Mar 03 '15 at 15:43
  • @Michael nearly. Its not so much finding out the info they have and whether the restriction is therefore satisfied but, given some info, is the restriction satisfied. So, to try an use your example, say I have a sub class of Person called Michael and a restriction on the class that says "All Michaels must have a first name that is either Michael or Mike" I want to say, given the first name Michael, give me all classes whose restrictions are satisfied, which in this case would be Michael. – bakersman Mar 03 '15 at 16:19
  • it's not quite the same question, but you might find [Is it possible to express a recursive definition in SPARQL?](http://stackoverflow.com/q/25256452/1281433) helpful. Especially the discussion about finding individuals that match a set of constraints, versus finding individuals that violate a set of constraints. – Joshua Taylor Mar 09 '15 at 21:23

2 Answers2

2

You can do some of what you're talking about, but it's important to remember that OWL is based on open world reasoning. This means that if you haven't explicitly said something, and you don't have a way to infer whether it's true or false, OWL doesn't assume either way; it's just unknown. For instance, if you only say "John loves Mary", then you haven't said that "John loves Sue" (obviously), but you also haven't says that "John does not love Sue."

For instance, you might say that: "Man ⊑ ∀ owns.Hat" ("Men own only hats."). Now, that's not a definition, so you can't just say that because something only owns hats, it's a man. You can find some violations, if you can find something that claims to be a Man, but owns something that is not a hat. (Of course, finding something that's definitely not a hat requires some reasoning, because with the open-world assumption, it's often hard to know what something is not than to know what it is.)

All that said, you can do some kinds of things with your ontology and SPARQL. Let's recreate some of the data first:

@prefix :      <http://stackoverflow.com/q/28812904/1281433/> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

:       a       owl:Ontology .
:A      a       owl:Class .
:C      a       owl:Class .
:D      a       owl:Class .
:E      a       owl:Class .
:F      a       owl:Class .
:G      a       owl:Class .
:H      a       owl:Class .

:isConfirmedBy  a  owl:ObjectProperty .

:B      a                owl:Class ;
        rdfs:subClassOf  :A ;
        rdfs:subClassOf  [ a                   owl:Restriction ;
                           owl:onProperty      :isConfirmedBy ;
                           owl:someValuesFrom  [ a                   owl:Class ;
                                                 owl:intersectionOf  ( :E :F :G :H )
                                               ]
                         ] ;
        rdfs:subClassOf  [ a                  owl:Restriction ;
                           owl:allValuesFrom  [ a                   owl:Class ;
                                                owl:intersectionOf  ( :C :D )
                                              ] ;
                           owl:onProperty     :isConfirmedBy
                         ] .

First, lets look at how you can find (possible) violations. You could find a violation if you found something claiming to be a Man that was confirmed by something that's not a C and a D, or that is not confirmed by an E, F, G, or H. Again, I have to stress that this is very difficult, because usually what happens is that you'd say something like:

B &sqsubseteq; ∀ isConfirmedBy.(C &sqcap; D)
β : B
isConfirmedBy(β,x)

This isn't inconsistent, even if you don't know that x is a C and that x is a D. Instead, from this, you can infer that

x : (C &sqcap; D)

and then from that, you can infer that:

x : C
x : D

So, based on:

I am trying to write a query on a class with a restriction defined on it, that will determine whether the restriction has been satisfied and, if it has, return it.

it sounds like you're asking for a query that would return candidate instances of B. These would be things that so far as we know don't violate the negative conditions of membership, and meet the positive conditions of membership. In this case, you'd be looking for things that:

  1. are not confirmed by any things that are not both C's and D's
  2. are confirmed by something that is an E, F, G, or H.

You can write that like:

select ?candidate where {
  #-- find candidates that are confirmed by
  #-- by something that's an E, F, G, or H.
  values ?type { :E :F :G :H }
  ?candidate :isConfirmedBy/rdf:type ?type

  #-- But remove any that are confirmed by 
  #-- by something that's is *not* both a C
  #-- and a D.
  filter exists {
    ?candidate :isConfirmedBy ?x
    filter not exists { ?x a :C, :D }
  }
}

Note that this does not ensure that each candidate is actually a B, since there are still things that could be true about the candidate that we do not know yet.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Thanks for the great response. I guess the way we are using our ontology isn't truely open world as for our purposes we only need to know that it is "highly likely" our candidate is what we say it is. To use a real example, we have a candidate "Pregnant" and deduce it is highly likely that you are pregnant if you are both Female AND Aged Between 12 and 54 AND that you have also, say, Missed a period OR Have morning sickness. Obviously there are many violations to that but as I say, we only need to know it is likely, to be able to act on it. – bakersman Mar 11 '15 at 10:48
  • I've not had the chance to fully investigate your answer but its certainly given food for thought and offered a new approach to solving the problem, so thank you! – bakersman Mar 11 '15 at 10:49
1

I don't have your ontology, but with a made up version of my own, I came up with the following strategy. If I understand correctly, the presence of ThingC and ThingD are essential also one of ThingE, ThingF or ThingG must exists. So essentially I think you need an intersection of three queries.

SELECT distinct * 
Where {
{?thing rdfs:subClassOf ?restriction .
?restriction (owl:allValuesFrom | owl:someValuesFrom)/(owl:intersectionOf | owl:unionOf) ?list .
 FILTER EXISTS { 
    ?list rdf:rest*/rdf:first ?things.
    FILTER( (?things in (:ThingE, :ThingF,  :ThingG)) )
}}
{
?thing rdfs:subClassOf ?restriction .
?restriction (owl:allValuesFrom | owl:someValuesFrom)/(owl:intersectionOf | owl:unionOf) ?list .
FILTER  EXISTS { 
    ?list rdf:rest*/rdf:first ?things.
    FILTER( (?things in (:ThingD)) )
}}
{
?thing rdfs:subClassOf ?restriction .
?restriction (owl:allValuesFrom | owl:someValuesFrom)/(owl:intersectionOf | owl:unionOf) ?list .
FILTER  EXISTS { 
    ?list rdf:rest*/rdf:first ?things.
    FILTER( (?things in (:ThingC)) )
}}
}

I am still not sure, when having defined classes with axioms such as ThingB subClassOf hasRestriciton some ThingC and ThingB subClassOf hasRestriciton some ThingD should be part of the answer your are seeking or not. In this case, it won't come up.

Artemis
  • 3,271
  • 2
  • 20
  • 33