You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by Joshua TAYLOR <jo...@gmail.com> on 2011/10/07 21:13:09 UTC

Creating anonymous inverse object properties

Hello all,
I'm trying to programmatically construct the axiom

C SubClassOf ( inverse(P) some D)

I'd hoped to do something like:

ObjectProperty = inverseP.createObjectProperty();
inverseP.addInverseOf( m.getObjectProperty( NS + "P" ) );
m.createClass( NS + "C" )
  .addSubClass( m.createSomeValuesFromRestriction( null, inverseP,
m.getOntClass( NS + "D" ) ) );

but this doesn't work, since there's no version of
createObjectProperty that doesn't require any arguments, and the
String argument to createObjectProperty is required to be non-null.
At the same time, the axiom construction seems to be simple enough, so
I figure someone must know how to get an ObjectProperty for something
like inverse(P) without having given it a name.  What's the trick?

Thanks in advance,
//JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Re: Creating anonymous inverse object properties

Posted by Joshua TAYLOR <jo...@gmail.com>.
On Fri, Oct 7, 2011 at 5:08 PM, Joshua TAYLOR <jo...@gmail.com> wrote:
> 2) I'm only constructing this model to eventually be used with a
> Pellet reasoner, so would it be OK to add the subclass axiom by
> skipping the OntModel altogether and just adding the appropriate RDF
> representation of the axiom?

After a few moments, I thought I should clarify, lest it sound like
I'm asking for something I'm not.

I've written some Ruby code that generates some instance data (and a
couple of subclass axioms).  This code works at the RDF/triples level
rather than the OWL level (though I did define a few helper procedures
to make some common OWL constructions easier).  I'm now translating
this Ruby code to Java to consolidate the code.

I'd started using an OntModel because it seemed like it would be a bit
easier to do the ontological constructions.  Most of the data is
pretty simple though, and it wouldn't be much more trouble to do it
directly at the RDF level.  Though it's handy to be able to use the
OntModel to browse the data, I don't really need that capability at
the moment.  I'm just constructing the model to use later with a
Pellet reasoner.  If the Pellet reasoner sees the underlying (non
OntModel) Model, and gets what it needs from the RDF directly, then I
don't mind working at the RDF level.

If I take this approach (working at the RDF/triples level), it would
be fine to use a blank node in as a "name" for the property, right?
And Pellet would still get to see it in the proper OWL DL way, right?

Thanks for your help and patience,
//JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Re: Creating anonymous inverse object properties

Posted by Dave Reynolds <da...@gmail.com>.
On Sat, 2011-10-08 at 15:31 -0400, Joshua TAYLOR wrote:

> Now, the question still remains, although the Jena OntModel is only
> for OWL 1, if I create an object property in this manner (where the
> underlying RDF describes OWL 2 constructs), and use a Pellet Reasoner,
> will the Pellet Reasoner see the OWL 2 constructs as it ought to? 

Should do. The Ont API is just a convenient way of generating the RDF
triples, there's no hidden state and Pellet just sees the triples. So
long as the expression you are encoding matches the specs in [1] then I
assume Pellet will be happy with it.

Dave

[1] http://www.w3.org/TR/owl2-mapping-to-rdf/



Re: Creating anonymous inverse object properties

Posted by Joshua TAYLOR <jo...@gmail.com>.
On Sat, Oct 8, 2011 at 10:27 AM, Dave Reynolds
<da...@gmail.com> wrote:
> On Fri, 2011-10-07 at 18:00 -0400, Joshua TAYLOR wrote:
>
> I've not followed this entire thread but the following jumped out at
> me ...
>
>> At any rate, what I think I'm supposed to take away from this is that
>> RDF triples have to have URIs as their predicate, but Restrictions
>> only have to have rdfs:Properties as their owl:onProperty, and there
>> can be rdfs:Properties that aren't URIs (e.g., blank nodes).  However,
>> the only rdfs:Properties that can be used as *Jena* Properties are
>> URIs.  Does this sound right?
>
> Not quite. It's more complicated than that.
>
> OWL DL (and its many variants) impose a lot more syntactic constraints
> than simply the rdfs:range of owl:onProperty implies. In particular,
> there are a lot of restrictions on where you can use bNodes.

Ah, good point.  I spoke too loosely indeed.  A better version would
be:  while the object of owl:onProperty is typically a URIreference,
but in certain circumstances, viz., describing an inverse object
property, owl:onProperty may have a blank node as its object.

> So in OWL 2 DL there is a syntactic allowance for declaring anonymous
> inverses but it's a special case. You can't just go sticking arbitrary
> bNodes anywhere you see a rdf:Property and expect it to still be DL.

Right.

> The Jena OntAPI currently only supports OWL 1. If it gets extended to
> OWL 2 then it will need some way to handle anonymous inverses.
>
> In the meantime you can create anonymous inverses manually for use in
> restrictions:
>
>    ont.setStrictMode(false);
>    ObjectProperty p = ont.createObjectProperty(NS + "p");
>    ObjectProperty ip =
>        ont.createResource()
>         .addProperty(OWL.inverseOf, p)
>         .as(ObjectProperty.class);

Many thanks for this!  This is *far* nicer than the RDF-based way I did this.

Now, the question still remains, although the Jena OntModel is only
for OWL 1, if I create an object property in this manner (where the
underlying RDF describes OWL 2 constructs), and use a Pellet Reasoner,
will the Pellet Reasoner see the OWL 2 constructs as it ought to?  My
guess is "yes" (based on the assumption that Pellet gets to see all
the underlying triples and knows how to interpret the OWL constructs
therein), but I'll find out for sure soon enough through
experimentation.

Thanks!
//JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Re: Creating anonymous inverse object properties

Posted by Dave Reynolds <da...@gmail.com>.
On Fri, 2011-10-07 at 18:00 -0400, Joshua TAYLOR wrote:

I've not followed this entire thread but the following jumped out at
me ...

> At any rate, what I think I'm supposed to take away from this is that
> RDF triples have to have URIs as their predicate, but Restrictions
> only have to have rdfs:Properties as their owl:onProperty, and there
> can be rdfs:Properties that aren't URIs (e.g., blank nodes).  However,
> the only rdfs:Properties that can be used as *Jena* Properties are
> URIs.  Does this sound right?

Not quite. It's more complicated than that.

OWL DL (and its many variants) impose a lot more syntactic constraints
than simply the rdfs:range of owl:onProperty implies. In particular,
there are a lot of restrictions on where you can use bNodes.

If we ignore DataProperties and just think about ObjectProperties
then ...

In OWL (1) DL the class restrictions could only apply to an
individualvaluedPropertyID which must be a URIreference (i.e. no blank
nodes). Likewise inverseOf applies only to an
individualvaluedPropertyID.

In OWL 2 DL then class restrictions apply to ObjectPropertyExpressions
and an ObjectPropertyExpression is now either an ObjectProperty (which
must be an IRI) or ObjectInverseOf(ObjectProperty). [1]

So in OWL 2 DL there is a syntactic allowance for declaring anonymous
inverses but it's a special case. You can't just go sticking arbitrary
bNodes anywhere you see a rdf:Property and expect it to still be DL.

Of course, in OWL full you can do anything you like so long as it is
syntactically legal at the RDF level.

The Jena OntAPI currently only supports OWL 1. If it gets extended to
OWL 2 then it will need some way to handle anonymous inverses.

In the meantime you can create anonymous inverses manually for use in
restrictions:

    ont.setStrictMode(false);
    ObjectProperty p = ont.createObjectProperty(NS + "p");
    ObjectProperty ip = 
        ont.createResource()
         .addProperty(OWL.inverseOf, p)
         .as(ObjectProperty.class);

Dave

[1]
http://www.w3.org/TR/2009/REC-owl2-syntax-20091027/#Inverse_Object_Properties



Re: Creating anonymous inverse object properties

Posted by Joshua TAYLOR <jo...@gmail.com>.
On Fri, Oct 7, 2011 at 5:08 PM, Joshua TAYLOR <jo...@gmail.com> wrote:
> On Fri, Oct 7, 2011 at 4:27 PM, Ian Dickinson <ia...@epimorphics.com> wrote:
>> I think this is one of those cases where the DL worldview and the RDF
>> worldview collide. RDF is an edge-labelled directed graph: there are no
>> edges without labels. In other words, there are no triples with anonymous
>> predicates, so no way of creating a Property object (or ObjectProperty, etc)
>> without a URI.
>>
>> You'll have to generate skolem constants for the names of the inverse(P)
>> properties.
>
> Thanks for the quick response!  I still have a little bit of confusion, though:
>
> What would be used as skolem constants in this context?  I'd though
> that this was a situation for blank nodes, and was essentially what,
> e.g., createClass() does for class names, i.e., creating a blank node
> for the class when the class doesn't have a specific name.  But I'm
> not sure how to get a blank node reference to use for the property
> expression (that I can convert to a property expression when I need
> to).

Sorry for so many replies to myself today, but hopefully it's saving
someone else some trouble.  Since  [1]

"""An RDF triple contains three components:
    the subject, which is an RDF URI reference or a blank node
    the predicate, which is an RDF URI reference
    the object, which is an RDF URI reference, a literal or a blank node.
An RDF triple is conventionally written in the order subject, predicate, object.
The predicate is also known as the property of the triple."""

I see why the predicate of a triple can't be a blank node. The range
of owl:onProperty, however, includes blank nodes, and that's why the
DL view can allow for inverses without names, and then the semantics
of OWL takes care of the rest.

Of course, now, because I was curious, I went and looked up the
rdfs:range of owl:onProperty in the OWL namespace [2] it happens to be
rdf:Property:

<rdf:Property rdf:about="http://www.w3.org/2002/07/owl#onProperty">
<rdfs:comment>The property that determines the property that a
property restriction refers to.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.w3.org/2002/07/owl#Restriction"/>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2002/07/owl#"/>
<rdfs:label>onProperty</rdfs:label>
<rdfs:range rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Property>

Looking up rdf:Property from [3]

<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property">
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
<rdfs:label>Property</rdfs:label>
<rdfs:comment>The class of RDF properties.</rdfs:comment>
<rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/>
</rdfs:Class>

So while the predicate of a *triple* must be a URI, Properties needn't
be.  And on top of that, the rdfs:range of rdf:predicate from the
reification syntax isn't rdf:Property, but rdf:Resource [3]!

<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate">
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
<rdfs:label>predicate</rdfs:label>
<rdfs:comment>The predicate of the subject RDF statement.</rdfs:comment>
<rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"/>
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/>
</rdf:Property>

At any rate, what I think I'm supposed to take away from this is that
RDF triples have to have URIs as their predicate, but Restrictions
only have to have rdfs:Properties as their owl:onProperty, and there
can be rdfs:Properties that aren't URIs (e.g., blank nodes).  However,
the only rdfs:Properties that can be used as *Jena* Properties are
URIs.  Does this sound right?

//JT

[1] http://www.w3.org/TR/2004/REC-rdf-concepts-20040210/#section-triples
[2] http://www.w3.org/2002/07/owl
[3] http://www.w3.org/1999/02/22-rdf-syntax-ns#Property

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Re: Creating anonymous inverse object properties

Posted by Joshua TAYLOR <jo...@gmail.com>.
On Fri, Oct 7, 2011 at 4:27 PM, Ian Dickinson <ia...@epimorphics.com> wrote:
> I think this is one of those cases where the DL worldview and the RDF
> worldview collide. RDF is an edge-labelled directed graph: there are no
> edges without labels. In other words, there are no triples with anonymous
> predicates, so no way of creating a Property object (or ObjectProperty, etc)
> without a URI.
>
> You'll have to generate skolem constants for the names of the inverse(P)
> properties.

Thanks for the quick response!  I still have a little bit of confusion, though:

What would be used as skolem constants in this context?  I'd though
that this was a situation for blank nodes, and was essentially what,
e.g., createClass() does for class names, i.e., creating a blank node
for the class when the class doesn't have a specific name.  But I'm
not sure how to get a blank node reference to use for the property
expression (that I can convert to a property expression when I need
to).  After I sent my initial message, I'd tried going along this
route via the following:


OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_MEM );
OntClass c = m.createClass( "C" );
OntClass d = m.createClass( "D" );
OntProperty p = m.createObjectProperty( "p" );
OntProperty invP = m.createOntResource( null ).asObjectProperty();
invP.addInverseOf( p );
c.addSuperClass( m.createSomeValuesFromRestriction( null, invP, d ) );


but this throws an Exception


     [java] Exception in thread "main"
com.hp.hpl.jena.ontology.ConversionException: Cannot convert node
-684af14a:132e028a5b2:-7ffc to ObjectProperty
     [java]     at
com.hp.hpl.jena.ontology.impl.ObjectPropertyImpl$1.wrap(ObjectPropertyImpl.java:70)
     [java]     at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:142)
     [java]     at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:22)
     [java]     at
com.hp.hpl.jena.enhanced.Polymorphic.asInternal(Polymorphic.java:54)
     [java]     at com.hp.hpl.jena.enhanced.EnhNode.as(EnhNode.java:97)
     [java]     at
com.hp.hpl.jena.ontology.impl.OntResourceImpl.asObjectProperty(OntResourceImpl.java:1062)


Now, for what it's worth, if I write an ontology outside of Jena
containing a class expression like


(inverse(P) some D)


and load the ontology into Jena, Jena will confirm that the class is a
Restriction, that it's a someValuesFromRestriction, but then gives me
the same sort of Exception when I try to getOnProperty().  So I guess
Jena's really not expecting to see blank nodes as properties. So:

1) What kind of entity is supposed to be used as a skolem constant?
2) I'm only constructing this model to eventually be used with a
Pellet reasoner, so would it be OK to add the subclass axiom by
skipping the OntModel altogether and just adding the appropriate RDF
representation of the axiom?

Thanks,
//JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Re: Creating anonymous inverse object properties

Posted by Ian Dickinson <ia...@epimorphics.com>.
Hi Joshua,

On 07/10/11 20:13, Joshua TAYLOR wrote:
> Hello all,
> I'm trying to programmatically construct the axiom
>
> C SubClassOf ( inverse(P) some D)
>
> I'd hoped to do something like:
>
> ObjectProperty = inverseP.createObjectProperty();
> inverseP.addInverseOf( m.getObjectProperty( NS + "P" ) );
> m.createClass( NS + "C" )
>    .addSubClass( m.createSomeValuesFromRestriction( null, inverseP,
> m.getOntClass( NS + "D" ) ) );
>
> but this doesn't work, since there's no version of
> createObjectProperty that doesn't require any arguments, and the
> String argument to createObjectProperty is required to be non-null.
> At the same time, the axiom construction seems to be simple enough, so
> I figure someone must know how to get an ObjectProperty for something
> like inverse(P) without having given it a name.  What's the trick?
I think this is one of thoese cases where the DL worldview and the RDF 
worldview collide. RDF is an edge-labelled directed graph: there are no 
edges without labels. In other words, there are no triples with 
anonymous predicates, so no way of creating a Property object (or 
ObjectProperty, etc) without a URI.

You'll have to generate skolem constants for the names of the inverse(P) 
properties.

Ian



-- 
____________________________________________________________
Ian Dickinson                   Epimorphics Ltd, Bristol, UK
mailto:ian@epimorphics.com        http://www.epimorphics.com
cell: +44-7786-850536              landline: +44-1275-399069
------------------------------------------------------------
Epimorphics Ltd.  is a limited company registered in England
(no. 7016688). Registered address: Court Lodge, 105 High St,
               Portishead, Bristol BS20 6PT, UK