5

I am building a smart home ontology. I now have a class hierarchy like that:enter image description here

I want to give definitions to the subclass of 'RoomStatus'. For example, I want to define that when room temperature is in range of 18-22 Centigrade and Humidity is in range of 40-50%, then the room has a mild status. I tried to use Class Expression Editor in Protege but it doesn't work.

How can I realize this definition? Thanks in advance!

Ev3rlasting
  • 2,145
  • 4
  • 18
  • 31

3 Answers3

4

Hatim's answer may work for you, but I think it might be better not to use equivalent class axioms when you don't have to, and to avoid tying Mild Status to particular temperatures and humidities. After all, what it means for a Room to have a mild status is very different for what it means for a Sauna to have a mild status.

I'd recommend using a General Class Axiom to say that:

If a Room has a temperature and a humidity within the specified ranges, then the Room has a mild status.

As a class axiom, that's:

Room and (hasTemperature some integer[≥18,≤22]) and (hasHumidity some integer[≥40,≤50]) subClassOf (hasStatus value Mild_Status)

That's almost exactly what you can write in Protege:

axiom in Protege

Here's the ontology (in RDF/XML and in TTL) with that axiom:

@prefix :      <https://stackoverflow.com/q/29228328/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 .

:Room   a       owl:Class .
:Status  a      owl:Class .
:Mild_Status  a  owl:NamedIndividual , :Status .

:hasStatus  a   owl:ObjectProperty .

:hasTemperature  a  owl:DatatypeProperty .
:hasHumidity  a  owl:DatatypeProperty .

[ a                   owl:Class ;
  rdfs:subClassOf     [ a               owl:Restriction ;
                        owl:hasValue    :Mild_Status ;
                        owl:onProperty  :hasStatus
                      ] ;
  owl:intersectionOf  ( :Room _:b2 _:b3 )
] .

_:b3    a                   owl:Restriction ;
        owl:onProperty      :hasTemperature ;
        owl:someValuesFrom  [ a                     rdfs:Datatype ;
                              owl:onDatatype        xsd:integer ;
                              owl:withRestrictions  ( _:b0 _:b4 )
                            ] .
_:b0    xsd:minInclusive  18 .
_:b4    xsd:maxInclusive  22 .

_:b2    a                   owl:Restriction ;
        owl:onProperty      :hasHumidity ;
        owl:someValuesFrom  [ a                     rdfs:Datatype ;
                              owl:onDatatype        xsd:integer ;
                              owl:withRestrictions  ( _:b5 _:b1 )
                            ] .
_:b1    xsd:minInclusive  40 .
_:b5    xsd:maxInclusive  50 .
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns="https://stackoverflow.com/q/29228328/1281433/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
  <owl:Ontology rdf:about="https://stackoverflow.com/q/29228328/1281433/"/>
  <owl:Class rdf:about="https://stackoverflow.com/q/29228328/1281433/Room"/>
  <owl:Class rdf:about="https://stackoverflow.com/q/29228328/1281433/Status"/>
  <owl:Class>
    <rdfs:subClassOf>
      <owl:Restriction>
        <owl:onProperty>
          <owl:ObjectProperty rdf:about="https://stackoverflow.com/q/29228328/1281433/hasStatus"/>
        </owl:onProperty>
        <owl:hasValue>
          <owl:NamedIndividual rdf:about="https://stackoverflow.com/q/29228328/1281433/Mild_Status">
            <rdf:type rdf:resource="https://stackoverflow.com/q/29228328/1281433/Status"/>
          </owl:NamedIndividual>
        </owl:hasValue>
      </owl:Restriction>
    </rdfs:subClassOf>
    <owl:intersectionOf rdf:parseType="Collection">
      <owl:Class rdf:about="https://stackoverflow.com/q/29228328/1281433/Room"/>
      <owl:Restriction>
        <owl:onProperty>
          <owl:DatatypeProperty rdf:about="https://stackoverflow.com/q/29228328/1281433/hasHumidity"/>
        </owl:onProperty>
        <owl:someValuesFrom>
          <rdfs:Datatype>
            <owl:onDatatype rdf:resource="http://www.w3.org/2001/XMLSchema#integer"/>
            <owl:withRestrictions rdf:parseType="Collection">
              <rdf:Description>
                <xsd:maxInclusive rdf:datatype="http://www.w3.org/2001/XMLSchema#integer"
                >50</xsd:maxInclusive>
              </rdf:Description>
              <rdf:Description>
                <xsd:minInclusive rdf:datatype="http://www.w3.org/2001/XMLSchema#integer"
                >40</xsd:minInclusive>
              </rdf:Description>
            </owl:withRestrictions>
          </rdfs:Datatype>
        </owl:someValuesFrom>
      </owl:Restriction>
      <owl:Restriction>
        <owl:onProperty>
          <owl:DatatypeProperty rdf:about="https://stackoverflow.com/q/29228328/1281433/hasTemperature"/>
        </owl:onProperty>
        <owl:someValuesFrom>
          <rdfs:Datatype>
            <owl:onDatatype rdf:resource="http://www.w3.org/2001/XMLSchema#integer"/>
            <owl:withRestrictions rdf:parseType="Collection">
              <rdf:Description>
                <xsd:minInclusive rdf:datatype="http://www.w3.org/2001/XMLSchema#integer"
                >18</xsd:minInclusive>
              </rdf:Description>
              <rdf:Description>
                <xsd:maxInclusive rdf:datatype="http://www.w3.org/2001/XMLSchema#integer"
                >22</xsd:maxInclusive>
              </rdf:Description>
            </owl:withRestrictions>
          </rdfs:Datatype>
        </owl:someValuesFrom>
      </owl:Restriction>
    </owl:intersectionOf>
  </owl:Class>
</rdf:RDF>
Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Nice Design! In this case, `Mild_Status` is an individual, the member of `Status`. We can describe both conditions as "Mild is Status". So there is an important question, when should we use `member` and when should we use `subclass` to build ontology? Thanks! – Ev3rlasting Mar 24 '15 at 16:24
  • @Ev3rlasting That's a rather general question, and there's no universal answer. In this case, I think that having Status as a class makes sense, with a few Status individuals such as Mild, Extreme, etc. An alternative would be to have MildStatus, ExtremeStatus, etc., as subclasses of Status, but then you have to ask "what would the individuals be"? Does it make sense to have mildStatus72, mildStatus73, mildStatus74, etc.? If so, what distinguishes them? In this case, I don't see a need for that type of granularity, at least not yet. – Joshua Taylor Mar 24 '15 at 16:41
  • Thank you very much! Sorry my question took you a lot of time. But there is another one:) Is `Room` the domain of `hasTemperature` `hasHumidity` and hasStatus`? What is the use of `subClassOf` in the axiom? Whose subclass? Thank you! – Ev3rlasting Mar 24 '15 at 17:11
  • You can add those domains if you want to. If you do, then you won't need to say *(Room **and** (hasTemperature ...) **and** (hasHumidity ...))*, you can just say *((hasTemperature ...) **and** (hasHumidity ...))* since having a temperature or humidity will be enough to infer that something is a *Room*. I wouldn't necessarily want to say that the domain of those properties is *Room*, since other things could have temperatures, right? E.g., couldn't a Cooker have a temperature? Couldn't a sensor have a status (e.g., Malfunctioning, Operational, etc.)? – Joshua Taylor Mar 24 '15 at 17:31
  • @Ev3rlasting In general, a subclass axiom *C SubClassOf D* says that "**if** something is a C, **then** that something is a D." In this case, the subclass axiom says that "**if** something is a Room and has a temperature in the given range and has a humidity in the given range, **then** is has the status MildStatus." That's what you were trying to represent, right? – Joshua Taylor Mar 24 '15 at 17:32
  • Hey Joshua! I used your method and it works! Thank you! I have another question when I am implementing the ontology. I have a property :hasRoom, Home can hasRoom Room. I am using the general class axiom mentioned above: `Room and (hasTemperature some integer[≥18,≤22]) and (hasHumidity some integer[≥40,≤50]) subClassOf (hasStatus value Mild_Status)`. Now I want to infer that `If all the rooms belongs to the home hasStatus Mild_Status, then the home hasStatus Mild_Status`. I doubt that I can realize it using general class axiom, should I try Jena rules or SWRL? – Ev3rlasting Apr 20 '15 at 09:06
1

You can do it with class expression editor of Protege, but there is some steps to follow :

  1. You create the #Mild_status and make it subClassof #RoomStatus (you did it as I can see in your editor)

  2. You have to define the domain and the range of your two data properties (#centigrade and #humidity), for example having as domain the Class #RoomStatus and as range the xml datatype integer. All this can be done with Protege.

Finally, using the class expression editor: you have to assert that #Mild_status is equivalent to:

RoomStatus
 and (centigrade some integer[> 18])
 and (centigrade some integer[< 22])
 and (humidity some integer[> 40])
 and (humidity some integer[<50])

If you want to use this expression for instance retrieval reasoning: you have to be aware that not all the reasoners support data ranges reasoning. Pellet support this kind of expression but I think that Fact++ do not.

agamesh
  • 559
  • 1
  • 10
  • 26
Hatim
  • 71
  • 2
  • Thanks! It seems like that only when `RoomStatus` are `centigrade` and `humidity`'s domain, we can write like what you said. But the triples seem strange. For my opinion, i think it make more sense that when `Room hasSensor TemperatureSensor`, `Room hasSensor HumiditySensor` ,`TemperatureSensor hasCentigrade integer >18 and integer <20` ,`HumiditySensor hasHumidity integer>40 and integer <50`, we can have `RoomStatus hasStatus Mild`. Because it is the Sensor which can have reading rather than RoomStatus can have reading. What do you think? Thanks! – Ev3rlasting Mar 24 '15 at 12:04
  • 1
    Note that if the intent is to capture that "**if** room temperature is in the range ... **then** the room has a mild status", then a subclass axiom, rather than an equivalent class axiom might be more appropriate. – Joshua Taylor Mar 24 '15 at 13:41
  • I agree with @JoshuaTaylor , I used Class equivalence axiom, which is not appropriate in your case :) – Hatim Mar 24 '15 at 14:50
  • 1
    I'd still be a bit concerned about putting so many definite conditions on MildStatus. By relating MildStatus to RoomStatus and temperature and humidity, you lose the ability to talk about the MildStatus of, e.g., the weather. I'd rather (and added [an answer describing it](http://stackoverflow.com/a/29234453/1281433)) say that "rooms with certain properties" is a subclass of "rooms with mildstatus". That way, if a room has the condition, then it also has the mild status. – Joshua Taylor Mar 24 '15 at 14:55
0

This model does a good job of capturing key elements in the domain, but it suffers from a common error: the overuse of classes and sub-classes when instances would do a better job.

Let's look at Measurement. I infer that you mean not the taking of the measurement (an action) but the aspect to be measured, such as the status of the Fire Alarm. I would rename Measurement to MeasurementType, then represent the sub-classes of Measurement as instances of MeasurementType.

:_MeasurementType_FireAlarmReading a :MeasurementType, owl:NamedIndividual .
:_MeasurementType_GasReading a :MeasurementType, owl:NamedIndividual .

etc.

MeasurementType is a category class, and its instances define specific categories into which the measurements are placed.

The actual measurement is an event, with a start and end time. Each instance gets related to the type of measurement through a 'isCategorizedBy' property.

:_Measurement_gas_reading_2023-04-30T13-18-33 a :Measurement ;
:startDateTime '2023-04-30T13:18:33'^^xsd:dateTime ;
:endDateTime '2023-04-30T13:18:39'^^xsd:dateTime ;
:isCategorizedBy :_MeasurementType_GasReading ;
:hasMagnitude [ reference to a magnitude object that handles the numeric value and an appropriate unit of measure]
.

This pattern makes it easy to add other kinds of measurements later without introducing new sub-classes. You just add a new instance of MeasurementType, e.g.

:_MeasurementType_Radon_Level a :MeasurementType, owl:NamedIndividual .

Finally, I suggest you look at basing your model on the 'gist' upper ontology which provides many useful base classes and properties that you can extend to model your domain. https://www.semanticarts.com/gist/