On Mon, Mar 18, 2013 at 10:48 AM, Ed Swing <[email protected]> wrote:
> I noticed that the OntClass super/sub relationships do not seem to work
> properly. Here is a definition of two classes that clearly establish a
> parent-child relationship:
>
> <owl:Class rdf:ID="TerrorAttack">
> <rdfs:subClassOf rdf:resource="#Killing" />
> <rdfs:subClassOf>
> <owl:Restriction>
> <owl:onProperty rdf:resource="#actor" />
> <owl:allValuesFrom rdf:resource="#TerrorAgent" />
> </owl:Restriction>
> </rdfs:subClassOf>
> </owl:Class>
> <owl:Class rdf:ID="AircraftHijacking">
> <rdfs:subClassOf rdf:resource="#TerrorAttack" />
> </owl:Class>
>
> So when I get a reference to the AircraftHijacking as an OntClass, and invoke
> getSuperClass(), I would expect to get a reference to the TerrorAttack class.
> But this does not happen. Here is the snippet of code:
>
> OntModel model =
>
> ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF);
> FileInputStream inStream =
> new FileInputStream("ontology/terrorism.xml");
> model.read(inStream, null);
> inStream.close();
> String uriBase = model.getNsPrefixURI("");
> OntClass cls = model.getOntClass(uriBase + "TerrorAttack");
> System.out
> .println("TerAtt: " + cls + " Super=" + cls.getSuperClass());
> for (Iterator<OntClass> iter = cls.listSubClasses(true); iter
> .hasNext();) {
> System.out.println("Sub: " + iter.next());
> }
> cls = model.getOntClass(uriBase + "AircraftHijacking");
> System.out.println("CLass=" + cls + " Super=" + cls.getSuperClass());
> System.out.flush();
> for (Iterator<OntClass> iter = cls.listSuperClasses(true); iter
> .hasNext();) {
> System.out.println(" CLS=" + iter.next());
> }
>
> And here is what is printed:
>
> TerAtt: http://blsdev1.vsticorp.com/terrorism#TerrorAttack
> Super=http://www.w3.org/2002/07/owl#Thing
> Sub: -60c2c7fc:13d7deb0ee3:-7fee
> CLass=http://blsdev1.vsticorp.com/terrorism#AircraftHijacking
> Super=http://www.w3.org/2000/01/rdf-schema#Resource
> CLS=-60c2c7fc:13d7deb0ee3:-7ff7
> CLS=-60c2c7fc:13d7deb0ee3:-7ff4
> CLS=-60c2c7fc:13d7deb0ee3:-7ffa
> CLS=-60c2c7fc:13d7deb0ee3:-7fec
> CLS=-60c2c7fc:13d7deb0ee3:-7ff6
> CLS=-60c2c7fc:13d7deb0ee3:-7ff8
> CLS=-60c2c7fc:13d7deb0ee3:-7ff9
> CLS=-60c2c7fc:13d7deb0ee3:-7fe4
> CLS=-60c2c7fc:13d7deb0ee3:-7fe5
> CLS=-60c2c7fc:13d7deb0ee3:-7fed
> CLS=-60c2c7fc:13d7deb0ee3:-7fef
> CLS=http://blsdev1.vsticorp.com/terrorism#NonCountry
> CLS=http://blsdev1.vsticorp.com/terrorism#TerrorAgent
> CLS=http://blsdev1.vsticorp.com/terrorism#Agent
>
> Note that the TerrorAttack's superclass is Thing, not Killing (or a reference
> to an anonymous class?). It has one child, which is incorrect - the
> TerrorAttack has multiple children in the ontology, including
> AircraftHijacking.
First, do note that superclass is not exactly the same as
parent-class. A class S is a superclass of T if every individual that
has type T also has type S. This could be a result of
subclass/superclass axioms on T and S, or through some intermediaries
(e.g., if S is a superclass of R and R is a superclass of T), or
through inference (e.g., if a reasoner can determine that every
instance of T must also be an instance of S). Since a given class can
have many superclasses and subclasses, there is no clearly defined
notion of parent-class in OWL. For instance, if I define C as the
intersection of A and B, then both A and B are superclasses of C, but
neither would really be called the parent.
Without seeing your whole ontology, we can't know whether there are
any incorrect results here, but there are some (trivially) correct
results there. owl:Thing is will be a superclass of any OWL class, so
it's a correct, if not particularly useful superclass. I'm a bit
surprised by rdf:Resource showing up, since I'm not sure whether it's
an owl:Class or not, but I suppose it is true that anything that is a
TerrorAttack is also an rdf:Resource. The blank nodes are probably
showing up as a result of various restrictions that have been declared
as superclasses (either direct or indirect). Similarly, every class
is both a superclass and a subclass of itself, so those are trivially
correct answers, though not particularly useful. Passing "true" to
true to listSubClasses and listSuperClasses will help to prune down
your results though, so that's good there.
> Then we get to AircraftHijacking. Its superclass is apparenty Resource
> (huh?). When I list all superclasses, I get a bunch of anonymous classes and
> then three classes in my ontology that are not only not the parent class(es),
> but are in fact disjoint with it. Those three classes are defined as unions
> of classes which are disjoint with TerrorAttack's (actual) parent:
>
> <owl:Class rdf:ID="Agent">
> <owl:unionOf rdf:parseType="Collection">
> <owl:Class rdf:about="#Person" />
> <owl:Class rdf:about="#Organization" />
> </owl:unionOf>
> </owl:Class>
>
> <owl:Class rdf:ID="Killing">
> <rdfs:subClassOf rdf:resource="#Event" />
> ...
> </owl:Class>
> <owl:Class rdf:ID="Event">
> ...
> <owl:disjointWith rdf:resource="#Person" />
> <owl:disjointWith rdf:resource="#Organization" />
> <owl:disjointWith rdf:resource="#Location" />
> </owl:Class>
>
> I need to be able to get the reference to the TerrorAttack OntClass from the
> AircraftHijacking OntClass. This seems like it should be trivial.
Again, without seeing your whole ontology, it's tough to diagnose
particular problems. I reproduced your ontology (to the extent that
you gave in your email) and ran some similar queries on it. The
following code prints the model and the results of the queries. I've
run the queries using the same OntModelSpec that you've been using, as
well as one for a Pellet-backed model. You might like the results
from the Pellet better than the ones from Jena, but it doesn't look
like either is going to give you the parent-child relationship that
you want. I hope this helps. If it doesn't provide what you need,
you'll probably need to write a particular query for get a (not "the",
because there might not be a unique one) closest declared superclass,
i.e., a superclass of C that is not C, but which does not have a
subclass (other than C) that is also a superclass of C. (That might
be easier to write using SPARQL than with the Jena OntModel API.)
//JT
public class SASTerror {
public static void main(String[] args) throws IOException {
for ( OntModelSpec spec : new OntModelSpec[] {
OntModelSpec.OWL_DL_MEM_RULE_INF, PelletReasonerFactory.THE_SPEC } ) {
System.out.println( "Using spec " + spec );
OntModel model = ModelFactory.createOntologyModel( spec
);
InputStream is = SASTerror.class.getResourceAsStream(
"sas-terror.owl" );
model.read( is, null );
is.close();
model.write( System.out, "N3" );
String ns = model.getNsPrefixURI( "" );
OntClass terrorAttack = model.getOntClass(
ns+"TerrorAttack" );
OntClass aircraftHijacking = model.getOntClass(
ns+"AircraftHijacking" );
for ( boolean direct : new boolean[] { true, false } ) {
System.err.println( "*
aircraftHijacking.getSuperClass() =
"+aircraftHijacking.getSuperClass() );
ExtendedIterator<OntClass> classes =
aircraftHijacking.listSuperClasses( direct );
while ( classes.hasNext() ) {
System.err.println( "\t* other
superclass: "+classes.next() );
}
System.err.println( "*
terrorAttack.getSubClass() =
"+terrorAttack.getSubClass() );
classes = terrorAttack.listSubClasses( direct );
while ( classes.hasNext() ) {
System.err.println( "\t* other
subclass: "+ classes.next() );
}
}
}
}
}
output (trimmed) a bit:
Using spec com.hp.hpl.jena.ontology.OntModelSpec@dda4f7b
@prefix : <http://example.com/sas-terror#> .
@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#> .
:Agent
a owl:Class ;
owl:equivalentClass
[ a owl:Class ;
owl:unionOf (:Organization :Person)
] .
:AircraftHijacking
a owl:Class ;
rdfs:subClassOf :TerrorAttack .
:TerrorAgent
a owl:Class .
:Location
a owl:Class .
:TerrorAttack
a owl:Class ;
rdfs:subClassOf :Killing ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:allValuesFrom :TerrorAgent ;
owl:onProperty :actor
] .
:Event
a owl:Class ;
owl:disjointWith :Location , :Person , :Organization .
:actor
a owl:ObjectProperty .
<http://example.com/sas-terror>
a owl:Ontology .
:Person
a owl:Class .
:Killing
a owl:Class ;
rdfs:subClassOf :Event .
:Organization
a owl:Class .
Queries using the Jena's reasoner:
* aircraftHijacking.getSuperClass() =
http://www.w3.org/2000/01/rdf-schema#Resource
* other superclass: http://example.com/sas-terror#TerrorAttack
* terrorAttack.getSubClass() = http://example.com/sas-terror#TerrorAttack
* other subclass: http://example.com/sas-terror#AircraftHijacking
* aircraftHijacking.getSuperClass() =
http://www.w3.org/2000/01/rdf-schema#Resource
* other superclass: http://www.w3.org/2000/01/rdf-schema#Resource
* other superclass: http://www.w3.org/2002/07/owl#Thing
* other superclass: http://example.com/sas-terror#TerrorAttack
* other superclass: http://example.com/sas-terror#Killing
* other superclass: -4b39b73b:13d7e35a059:-7ff8
* other superclass: http://example.com/sas-terror#Event
* terrorAttack.getSubClass() = http://example.com/sas-terror#TerrorAttack
* other subclass: http://example.com/sas-terror#AircraftHijacking
Queries using Pellet:
* aircraftHijacking.getSuperClass() = http://example.com/sas-terror#Killing
* other superclass: http://example.com/sas-terror#TerrorAttack
* terrorAttack.getSubClass() = http://www.w3.org/2002/07/owl#Nothing
* other subclass: http://example.com/sas-terror#AircraftHijacking
* aircraftHijacking.getSuperClass() = http://example.com/sas-terror#Killing
* other superclass: http://example.com/sas-terror#Killing
* other superclass: http://www.w3.org/2002/07/owl#Thing
* other superclass: http://example.com/sas-terror#Event
* other superclass: http://example.com/sas-terror#TerrorAttack
* terrorAttack.getSubClass() = http://www.w3.org/2002/07/owl#Nothing
* other subclass: http://www.w3.org/2002/07/owl#Nothing
* other subclass: http://example.com/sas-terror#AircraftHijacking
--
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/