3

The general problem

I'm working on a simple ontology, using Protégé 4.3 and trying to create a model such that every instance of a class C has some particular value v, which is an instance of a class V, for a given property p. I can get this inference using an axiom

C subClassOf (p value v)

but I think I want to be able to state this more along the lines of a

C subClassOf (p some V)

because I'd actually like each instance of C to be related to every instance of V.

A specific example

My example is automobiles and actions — I want to create a set of actions for automobiles. When I create new instances of automobiles I want each to have a set of actions. If I add new instances of actions I want all the instances of automobiles to reflect all their related actions.

To add further detail, I have defined the Auto class and two subclasses: Car and Truck. I have also defined an Action class and a subclass, TruckAction. I have defined a hasAction property with domain Auto and range Action to relate autos and actions. I have further created several individuals of different types:

  • Auto
    • Truck {F150}
    • Car {ChevyMalibu}
  • Action {Accelerate}
    • TruckAction {LoadCargo}

When I make Car a subclass of (hasAction value Accelerate), I can see that ChevyMalibu has the inferred object property hasAction Accelerate, but this seems akin to hard-coding the object property assertion. I would like to have all car actions inferred for the ChevyMalibu and likewise all TruckActions inferred for F150. I'm not quite sure why doing something like making Car a subclass of (hasAction some Action) won't get me there.

I think that the eloquent answer to OWL type inference with a restriction is related to my question, but I can't quite add this up.

Community
  • 1
  • 1
SW-SAP
  • 58
  • 4

1 Answers1

5

Encoding the rules

You correctly note that if an individual x is an instance of p value y, then you'll infer the assertion p(x,y). However, simply saying that x is an instance of p some Y doesn't (without some more information) won't let you infer that p(x,yi) for any particular yi, even if yi is the only particular instance of Y that you've declared. This is because OWL makes the open world assumption; just because you haven't said something is true (or false) yet doesn't mean that it couldn't be true (or false). (Of course, you might have already said other things that would let you figure out whether something is true or false.) This is described in more detail in another question, Why is this DL-Query not returning any individuals?

If I've understood it correctly, what you're trying to do is say something like:

  1. every Vehicle is related by hasAction to every Action
  2. every Car is related by hasAction to every CarAction
  3. every Truck is related by hasAction to every TruckAction

There are a couple of ways that you could do this. The easiest is to simply use some SWRL rules, and the other is called rolification.

Using SWRL Rules

You can write SWRL rule counterparts of the rules above, and the they're pretty easy to write:

Vehicle(?v) ∧ Action(?a) → hasAction(?v,?a)
Car(?v) ∧ CarAction(?a) → hasAction(?v,?a)
Truck(?v) ∧ TruckAction(?a) → hasAction(?v,?a)

If you use all of these rules, you'll find that each of your vehicles has more actions than you want it to, because, by the first rule, each vehicle is related to each action. E.g., since each TruckAction is also an Action, and since each Car is a Vehicle, the first rule will relate each TruckAction to each Car, and you didn't really want that. Even so, using some rules may well be the easiest option here.

Using Rolification

If you don't want to use SWRL rules, then another option is rolification. I've described rolification and how to do it in answers to a few questions, so you should have a look at:

Those will give you more details about rolification. The main point, though, is that we get new properties, e.g., RCar, that have a special behavior: they only relate instances of a particular class to that same instance. E.g., RCar relates each instance of Car to itself, and doesn't do anything else. It's effectively an equivalence relation on a particular class.

How is rolification useful here? It means that we can use subproperty chain axioms to infer some hasAction properties. E.g.,

hasAction ⊑ RCar • topObjectProperty • RCarAction

That's essentially equivalent to the SWRL rule (topObjectProperty is a built in property of OWL that relates everything to everything):

RCar(?c,?c) ∧ topObjectProperty(?c,?a) ∧ RCarAction(?a,?a) → hasAction(?c,?a)

There are two advantages, though:

  1. the subproperty chain axiom doesn't require a reasoner to have SWRL support; and
  2. the subproperty chain axiom works on all individuals, but the SWRL rule works only on named individuals, so you get somewhat better coverage.

You'll still have the same issue that you did with the specificity of the SWRL rules, though; if you say that every Vehicle is related to every Action by hasAction, then that subproperty chain will also apply to subclasses of vehicle and subclasses of action.

There's a significant disadvantage, though: for each class that you want to use in one of these "rules," you need a new property and an equivalent class axiom, and that gets to be sort of tedious.

A different hierarchy for actions

Because both the SWRL rule approach and the subproperty chain with rolification approaches have the problem that the generic rule that relates each vehicle to each action will capture all the actions from subclasses of Action and vehicles from subclasses of Vehicles, you may need to restructure one of your hierarchies a bit. I'd suggest that rather than

Action
  CarAction
  TruckAction

that you use

Action
  VehicleAction
  CarAction
  TruckAction

and not mirror the hierarchy that you have under Vehicle. This way you can write rules of the form:

every Vehicle is related to every GenericAction by hasAction
every Car is related to every CarAction by hasAction
every Truck is related to every TruckAction by hasAction

With SWRL rules

If you do this with SWRL rules, it looks like this:

enter image description here

(The default layout for Protégé might not include a place to edit SWRL rules though. See my answer to Ontology property definition in Protégé-OWL / SWRL for instructions on getting one. It's just a minor interface tweak; you don't need to download or install anything.) This produces results like this:

enter image description here

You can copy and paste this ontology:

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

:Action  a      owl:Class .

<urn:swrl#a>  a  swrl:Variable .

:DodgeRam  a    owl:NamedIndividual , :Truck .

:Truck  a                owl:Class ;
        rdfs:subClassOf  :Vehicle .

:Car    a                owl:Class ;
        rdfs:subClassOf  :Vehicle .

<urn:swrl#v>  a  swrl:Variable .

:LoadCargo  a   owl:NamedIndividual , :TruckAction .

[ a          swrl:Imp ;
  swrl:body  [ a          swrl:AtomList ;
               rdf:first  [ a                    swrl:ClassAtom ;
                            swrl:argument1       <urn:swrl#a> ;
                            swrl:classPredicate  :GenericAction
                          ] ;
               rdf:rest   [ a          swrl:AtomList ;
                            rdf:first  [ a                    swrl:ClassAtom ;
                                         swrl:argument1       <urn:swrl#v> ;
                                         swrl:classPredicate  :Vehicle
                                       ] ;
                            rdf:rest   ()

                          ]
             ] ;
  swrl:head  [ a          swrl:AtomList ;
               rdf:first  [ a                       swrl:IndividualPropertyAtom ;
                            swrl:argument1          <urn:swrl#v> ;
                            swrl:argument2          <urn:swrl#a> ;
                            swrl:propertyPredicate  :hasAction
                          ] ;
               rdf:rest   ()

             ]
] .

:Accelerate  a  owl:NamedIndividual , :GenericAction .

:F150   a       owl:NamedIndividual , :Truck .

:FordFocusZX5  a  owl:NamedIndividual , :Car .

[ a          swrl:Imp ;
  swrl:body  [ a          swrl:AtomList ;
               rdf:first  [ a                    swrl:ClassAtom ;
                            swrl:argument1       <urn:swrl#c> ;
                            swrl:classPredicate  :Car
                          ] ;
               rdf:rest   [ a          swrl:AtomList ;
                            rdf:first  [ a                    swrl:ClassAtom ;
                                         swrl:argument1       <urn:swrl#a> ;
                                         swrl:classPredicate  :CarAction
                                       ] ;
                            rdf:rest   ()

                          ]
             ] ;
  swrl:head  [ a          swrl:AtomList ;
               rdf:first  [ a                       swrl:IndividualPropertyAtom ;
                            swrl:argument1          <urn:swrl#c> ;
                            swrl:argument2          <urn:swrl#a> ;
                            swrl:propertyPredicate  :hasAction
                          ] ;
               rdf:rest   ()

             ]
] .

:Brake  a       owl:NamedIndividual , :GenericAction .

:hasAction  a   owl:ObjectProperty .

:GenericAction  a        owl:Class ;
        rdfs:subClassOf  :Action .

<https://stackoverflow.com/q/21512765/1281433/cars>
        a       owl:Ontology .

:Vehicle  a     owl:Class .

<urn:swrl#c>  a  swrl:Variable .

:ChevyMalibu  a  owl:NamedIndividual , :Car .

<urn:swrl#t>  a  swrl:Variable .

:CarAction  a            owl:Class ;
        rdfs:subClassOf  :Action .

[ a          swrl:Imp ;
  swrl:body  [ a          swrl:AtomList ;
               rdf:first  [ a                    swrl:ClassAtom ;
                            swrl:argument1       <urn:swrl#t> ;
                            swrl:classPredicate  :Truck
                          ] ;
               rdf:rest   [ a          swrl:AtomList ;
                            rdf:first  [ a                    swrl:ClassAtom ;
                                         swrl:argument1       <urn:swrl#a> ;
                                         swrl:classPredicate  :TruckAction
                                       ] ;
                            rdf:rest   ()

                          ]
             ] ;
  swrl:head  [ a          swrl:AtomList ;
               rdf:first  [ a                       swrl:IndividualPropertyAtom ;
                            swrl:argument1          <urn:swrl#t> ;
                            swrl:argument2          <urn:swrl#a> ;
                            swrl:propertyPredicate  :hasAction
                          ] ;
               rdf:rest   ()

             ]
] .

:TruckAction  a          owl:Class ;
        rdfs:subClassOf  :Action .

With rolification

If you do this with rolification, it looks like this: enter image description here

and you get the results you'd expect:

enter image description here

You can copy and paste this ontology:

@prefix :      <https://stackoverflow.com/q/21512765/1281433/cars#> .
@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#> .

:GenericAction  a            owl:Class ;
        rdfs:subClassOf      :Action ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_GenericAction
                             ] .

:Car    a                    owl:Class ;
        rdfs:subClassOf      :Vehicle ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_Car
                             ] .

:CarAction  a                owl:Class ;
        rdfs:subClassOf      :Action ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_CarAction
                             ] .

:R_TruckAction  a  owl:ObjectProperty .

:R_Car  a       owl:ObjectProperty .

:Truck  a                    owl:Class ;
        rdfs:subClassOf      :Vehicle ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_Truck
                             ] .

:Brake  a       owl:NamedIndividual , :GenericAction .

:hasAction  a                   owl:ObjectProperty ;
        owl:propertyChainAxiom  ( :R_Vehicle owl:topObjectProperty :R_GenericAction ) ;
        owl:propertyChainAxiom  ( :R_Car owl:topObjectProperty :R_CarAction ) ;
        owl:propertyChainAxiom  ( :R_Truck owl:topObjectProperty :R_TruckAction ) .

:R_CarAction  a  owl:ObjectProperty .

:R_Truck  a     owl:ObjectProperty .

:F150   a       owl:NamedIndividual , :Truck .

:Accelerate  a  owl:NamedIndividual , :GenericAction .

:Action  a      owl:Class .

:ChevyMalibu  a  owl:NamedIndividual , :Car .

:R_Vehicle  a   owl:ObjectProperty .

:FordFocusZX5  a  owl:NamedIndividual , :Car .

:R_GenericAction  a  owl:ObjectProperty .

:TruckAction  a              owl:Class ;
        rdfs:subClassOf      :Action ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_TruckAction
                             ] .

:DodgeRam  a    owl:NamedIndividual , :Truck .

<https://stackoverflow.com/q/21512765/1281433/cars>
        a       owl:Ontology .

:LoadCargo  a   owl:NamedIndividual , :TruckAction .

:Vehicle  a                  owl:Class ;
        owl:equivalentClass  [ a               owl:Restriction ;
                               owl:hasSelf     true ;
                               owl:onProperty  :R_Vehicle
                             ] .
Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Wow - thanks for the detailed answer! It will take me some time to digest that for sure. If your forthcoming book includes introductory logic I'll need to be purchasing a copy :) – SW-SAP Feb 03 '14 at 03:35
  • If we can live with the fact that the SWRL rules only work on named individuals, they certainly look to be easier to maintain. So if we thought we would operate in an environment without SWRL support (like maybe Virtuoso), could we use the "Export inferred axioms as ontology" option there? Any thoughts, if you have done that previously? – SW-SAP Feb 03 '14 at 23:22
  • @SW-SAP I'm not quite sure I follow. Do you mean loading ontology X in the Protégé, running the reasoner, exporting the results as ontology Y, and then loading Y into Virtuoso? You could certainly do that, I suppose. Of course, if you add more data to Y later, you won't be getting the results of rules that could be applied to it. – Joshua Taylor Feb 03 '14 at 23:25
  • Yes, that makes perfect sense. While our concepts of cars and trucks and "actions" won't change much, it's obvious to me now that any new individuals would not get these actions. – SW-SAP Feb 04 '14 at 04:10
  • So I cut and pasted the rolification example ontology you've provided above and cannot get the same result when running pellet. The property assertions on Actions are not inferred. I was able to see the inferences made in your Brady family ontology so I don't think it is a technical issue with installation of protege/pellet. Could you cut/paste your example back into protege and double check that you still get the same result? Much Thanks. – SW-SAP Feb 06 '14 at 04:16
  • Looks as though pellet is not making those inferences while FaCT++ and HermiT 1.3.8 are working. – SW-SAP Feb 07 '14 at 04:20
  • @SW-SAP I think I was using Pellet in those screenshots. What version of Protégé and Pellet are you using? Mine are: Protégé 4.2.0 and Pellet 2.2.0. – Joshua Taylor Feb 07 '14 at 13:28
  • Using Protégé 4.3.0 and Pellet 2.2.0. Also interesting - with pellet reasoner turned on, the Accelerate individual has object property "R_GenericAction Action" asserted - but for the Brake individual there are two object properties asserted, "hasAction Brake" and "R_GenericAction Brake". The LoadCargo individual just has "R_TruckAction LoadCargo". I'm wondering about "hasAction Brake" because if I switch to either of the other reasoners this goes away. – SW-SAP Feb 08 '14 at 02:00
  • @SW-SAP I wouldn't expect to see "Brake hasAction Brake". It's possible that I was using Hermit or FaCT, too (I should have checked when making the screenshots). – Joshua Taylor Feb 08 '14 at 14:15