3

I need to implement an OWL-ontology in Protégé, which contains a two classes: s1 and s2, both are the instances of System class. These two classes are connected by the connection class s1_s2, which contains property omega. This property has to take a value according to the following law:

omega = 1 * s1.complete

How can I implement it in Protégé in a such way, I could use it in SWRL-rule in the future?

class diagram fragment with connection between classes

Mike
  • 14,010
  • 29
  • 101
  • 161

1 Answers1

11

In general, you'd start by defining the classes and the properties that you need:

classes

object properties

datatype properties

At this point you could add some axioms that govern how the systems have to interact, how the properties work, etc. E.g., you might declare domains and ranges on your properties. Here's a domain and range on the hasS2 property:

hasS2 domain and range

You might also want to say that each InterSystem has exactly one associate S1 and S2:

hasS1 exactly 1 S1 …

To put in the mathematical constraints, you'll actually need SWRL; you won't be able to enforce the constraint using other kinds of OWL axioms. The rule you'd want is along the lines of the following. If you declare domains and ranges on your predicates, then you won't need all the type predicates that appear in this rule, since they could be inferred from the property usage.

S1(?s1) ∧ InterSystem(?i) ∧ hasS1(?i,?s1) ∧ hasComplete(?s1,?complete) multiply(?omega,1,?complete) → hasOmega(?i,?omega)

The multiplication here actually seems redundant, since you're multiplying by 1, so omega = alpha, in which case the head of that rule could simply be hasOmega(?i,?alpha). In Protégé the rule looks like this:

the rule

(In the version of Protégé that I'm using (not the latest), I had to Window > Create New Tab to create a Rules tab, and then Window > Views > Ontology Views > Rules to add the Rules list to the interface.)

The Turtle serialization of the RDF representation of this OWL ontology (which you can save and load into Protégé) is:

@prefix :      <http://stackoverflow.com/q/21499126/1281433/systems#> .
@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#> .

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

:hasComplete  a  owl:DatatypeProperty .

[ a          swrl:Imp ;
  swrl:body  [ a          swrl:AtomList ;
               rdf:first  [ a                    swrl:ClassAtom ;
                            swrl:argument1       <urn:swrl#i> ;
                            swrl:classPredicate  :InterSystem
                          ] ;
               rdf:rest   [ a          swrl:AtomList ;
                            rdf:first  [ a                    swrl:ClassAtom ;
                                         swrl:argument1       <urn:swrl#s1> ;
                                         swrl:classPredicate  :S1
                                       ] ;
                            rdf:rest   [ a          swrl:AtomList ;
                                         rdf:first  [ a                       swrl:IndividualPropertyAtom ;
                                                      swrl:argument1          <urn:swrl#i> ;
                                                      swrl:argument2          <urn:swrl#s1> ;
                                                      swrl:propertyPredicate  :hasS1
                                                    ] ;
                                         rdf:rest   [ a          swrl:AtomList ;
                                                      rdf:first  [ a                       swrl:DatavaluedPropertyAtom ;
                                                                   swrl:argument1          <urn:swrl#s1> ;
                                                                   swrl:argument2          <urn:swrl#complete> ;
                                                                   swrl:propertyPredicate  :hasComplete
                                                                 ] ;
                                                      rdf:rest   [ a          swrl:AtomList ;
                                                                   rdf:first  [ a               swrl:BuiltinAtom ;
                                                                                swrl:arguments  [ a          rdf:List ;
                                                                                                  rdf:first  <urn:swrl#omega> ;
                                                                                                  rdf:rest   [ a          rdf:List ;
                                                                                                               rdf:first  1 ;
                                                                                                               rdf:rest   ( <urn:swrl#complete> )
                                                                                                             ]
                                                                                                ] ;
                                                                                swrl:builtin    swrlb:multiply
                                                                              ] ;
                                                                   rdf:rest   ()

                                                                 ]
                                                    ]
                                       ]
                          ]
             ] ;
  swrl:head  [ a          swrl:AtomList ;
               rdf:first  [ a                       swrl:DatavaluedPropertyAtom ;
                            swrl:argument1          <urn:swrl#i> ;
                            swrl:argument2          <urn:swrl#omega> ;
                            swrl:propertyPredicate  :hasOmega
                          ] ;
               rdf:rest   ()

             ]
] .

:S2     a                owl:Class ;
        rdfs:subClassOf  :System .

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

:S1     a                owl:Class ;
        rdfs:subClassOf  :System .

:InterSystem  a          owl:Class ;
        rdfs:subClassOf  [ a                         owl:Restriction ;
                           owl:onClass               :S1 ;
                           owl:onProperty            :hasS1 ;
                           owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                         ] ;
        rdfs:subClassOf  [ a                         owl:Restriction ;
                           owl:onClass               :S2 ;
                           owl:onProperty            :hasS2 ;
                           owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                         ] .

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

<http://stackoverflow.com/q/21499126/1281433/systems>
        a       owl:Ontology .

:hasS2  a       owl:ObjectProperty .

:hasOmega  a    owl:DatatypeProperty .

:System  a      owl:Class .

:hasS1  a       owl:ObjectProperty .

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

That's a good start, but it's worthwhile to see how it all works. To see a place where the rules could be applied, we'll need some instance data and a reasoner. You mentioned that you can use Pellet from within Protégé, so we're all set on that count. For some instance data, let's create and InterSystem, its S1, and assign the S1's complete value.

the intersystem

the s1

You'll need to select the Pellet reasoner from the Reasoner menu, and then select Reasoner > Start Reasoner. At this point, you could run a DL query for “hasOmega value 42” to confirm that the individual has the desired property (make sure that you check the “Individuals” checkbox on the right):

enter image description here

If you navigate to the intersystem individual, you probably won't see the inferred value though. To show it, go to Reasoner > Configure… and check the Data Property Assertions option:

enter image description here

After that, you may need to restart the reasoner (Reasoner > None; Reasoner > Pellet; Reasoner > Start Reasoner), but afterward you'll be able to see the inferred values:

inferred data property assertion

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Dear Joshua. Thanks for the answer. I loaded the serialization of your implementation, but I can't find how exactly run the rule in Protégé 4.x? I created a Rule-tab, loaded rule view into this tab, there I see your rule: « InterSystem(?i), S1(?s1), hasS1(?i, ?s1), hasComplete(?s1, ?complete), multiply(?omega, 1, ?complete) -> hasOmega(?i, ?omega) », I switched to Pellet reasoner and started the reasoner, but I still don't see the results of the rule execution. Could you point me, please, where should I see the result. Thanks. – Mike Feb 01 '14 at 15:38
  • 1
    @Mike You can check that the inference is begin performed using a DL query, or (after turning on a configuration option) examining the individual. I've updated my answer to show how. – Joshua Taylor Feb 01 '14 at 19:29
  • Thanks for the detailed explanation. I tried to implement similar to «hasS1 exactly 1 S1» restriction/rule, but when I write: «exactly 1 * System.complete» in range of omega property I get the following error message: «Error: Invalid symbol message after ""». What's wrong with it? Why it doesn't allow me to define this assumption. All what I need is only to give a specific value to one class instance's property, based on the value of the property from specific instance. That's all. – Mike Feb 02 '14 at 14:57
  • 1
    @Mike I'm not sure what you mean by using "exactly 1 * System.complete" as a range. The range of an object property needs to be a class expression, an "exactly 1 * System.complete" certainly isn't one. What are you trying to express? – Joshua Taylor Feb 02 '14 at 23:17
  • Actually, in my model I'm trying to express the case when property will get the value of the property of another class instance. E.g. we have two rank systems: S1 and S2. Now we want to calculate an overall/average rank of item (S1_S2), based on the formula 0.5 * S1.rank + 0.5 * S2.rank. In order to do that I have to know how to get the value of the property from class S1, multiply it for 0.5 and store it in S1_S2.rank property. In classical programming languages (Java/C#/Ruby…) such kind of task is trivial, but how to implement this in Protege-OWL/SWRL world? – Mike Feb 03 '14 at 21:24
  • I need such thing in order to implement reasoning, based on SWRL/Pellet, I already wrote a Ruby-based version, now I have to implement the same stuff in Protege-OWL/SWRL. Thanks. – Mike Feb 03 '14 at 21:25
  • 1
    @Mike Classes don't have properties; individuals do. I'm not clear what you mean by "S1.rank", or what you mean by "how to get the value of the property from class S1". S1 is a class; it doesn't have properties; individuals of type S1 can have properties. Suppose you have data like: `x rdf:type S1 . x hasRank .34 . y rdf:type S2 . y hasRank .78 . z rdf:type S1_S2 . z hasS1 x . z hasS2 y.` Then a rule like the one I've described would compute the property value for the `z`. – Joshua Taylor Feb 03 '14 at 21:28
  • Thanks for the explanation, it's much more clear now. I have a question regarding to properties. I defined object properties, classes and individuals. When I created individuals I added properties manually, but when I executed reasoner I paid attention that now my individuals have a duplicate properties — one, that comes from manual filling and the other automatically with label «inferred». My question is should I add properties manually to individuals or that's the pointer of the reasoner, it adds properties automatically according to the definition? Thanks. – Mike Feb 07 '14 at 20:13