Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subclasses of Quantity are instances of Quantity too. #61

Closed
jbkoh opened this issue Aug 26, 2019 · 17 comments
Closed

Subclasses of Quantity are instances of Quantity too. #61

jbkoh opened this issue Aug 26, 2019 · 17 comments
Assignees

Comments

@jbkoh
Copy link
Contributor

jbkoh commented Aug 26, 2019

After OWL reasoning, Brick.ttl assumes that all the subclasses of brick:Quantity are instances of brick:Quantity too. Please check the regenerator code: https://gist.github.com/jbkoh/37fbec75d023eff23baeee0e7c721dd0
Quantity subclasses should not be instances, right?

I am also not sure if we want to instantiate brick:Quantity as entities. I see potential usage such as provenance tracking, but will it be actually used?

@gtfierro
Copy link
Member

Read through the section on Substances in the README: https://github.com/BrickSchema/Brick#substances we are punning substances by treating them as singletons. I think this makes the data model more intuitive. The plan is not to instantiate substances beyond the punned instances

@jbkoh
Copy link
Contributor Author

jbkoh commented Aug 26, 2019

I understand that's for Substances but my observation is for Quantities.

@gtfierro
Copy link
Member

Sorry! I got mixed up. Its the same principle though

@jbkoh
Copy link
Contributor Author

jbkoh commented Aug 26, 2019

I see, but I found that punning isn't applied to Substances. Can you verify that? The same query does not work for Substances.

And could you point out which part of the code enables the punning? I just want to understand how it's implemented.

@gtfierro
Copy link
Member

It's a little weird because we don't actually instantiate them anywhere, but I think I understand what's going on.

Punning is applied to both Quantities and Substances; the "pun" part is where we say that the value of a certain property is a single instance which is has the same name as the class. Loosely, this is lines https://github.com/BrickSchema/Brick/blob/master/generate_brick.py#L83-L84 instantiated by lines like https://github.com/BrickSchema/Brick/blob/master/sensor.py#L14. When this is serialized into the turtle file, it looks like https://github.com/BrickSchema/Brick/blob/master/Brick.ttl#L252-L254:

When we use a Quantity or Substance in this way as part of a definition, it becomes implicitly "instantiated" . So when you are doing your query above, because you are using a/rdf:type you are only getting the quantities and substances that have been used in an owl:Restriction clause with owl:hasValue. Eventually, when all of the substances and quantities are used in class restrictions, then they should all show up in your query.

However I would expect some of the substance classes to show up when doing that query. I'm not 100% sure why that's happening, but it smells like there's a bug somewhere. I'll investigate tomorrow

@jbulow
Copy link
Contributor

jbulow commented Sep 13, 2019

I assume this reaction from owlready2 when loading the Brick ontology is related:

`

@gtfierro
Copy link
Member

Good point! That probably has something to do with it. Wish it told us what was cyclic though.

We've uncovered that owlready2 doesn't provide all of the reasoning we require. owlrl does, but it can take a few hours to actually perform the reasoning. I'm running some tests + experiments to track down what's going on with this particular issue with instantiating Quantities and hope to have news to report soon.

@jbkoh how do you feel about quantities being instances? Temperature is a quantity and Operative_Temperature is a quantity, and Operative_Temperature is a type of Temperature. This approach to modelling involves both instantiation ("is a") and subclassing ("is a type of"). I think punning Quantities and Substances together is a decent solution to the modelling problem, in which case I'd like to close this issue once I figure out:

  • what (if any) is cyclic about the quantity or substance hierarchies
  • why substances and quantities are not consistently instantiated (this is linked to the reasoner)

@JoelBender
Copy link
Contributor

JoelBender commented Sep 15, 2019

I've been trying to reconcile this discussion with the SOSA/SSN model. I was expecting that brick:Sensor would be a subclass of sosa:Sensor, that a brick:Torque_Sensor is something that sosa:observes torque, an instance of a bacnet:AnalogInputOutput (something that might have an IRI like bacnet://234/analog-input.21) could also be an instance of a brick:Static_Pressure_Sensor.

@gtfierro
Copy link
Member

I think that's the right way of looking at it. Our brick:measures would be analogous to sosa:observes in this case, and I like the term "observes" better than "measures".

A related question, @JoelBender: is it more common to use rdfs:subClassOf or brick:equivalentClass in these scenarios where one is describing the relationship between two "equivalent" concepts?

@JoelBender
Copy link
Contributor

(assuming brick:equivalentClass is a typo for owl:equivalentClass) It is more common to use subclass because you can't necessarily guarantee that the two classes have exactly the same individuals. So sosa:observes probably can be used to observe things that brick can't measure, but I would expect that everything that Brick can measure be something that is a subclass of an observable property.

@gtfierro
Copy link
Member

I'm trying to implement some of these fixes in #76

I like that we differentiate between Substances and Quantities, but it would be useful to group both of these under an abstract "Measureable" class, which could be a subclass of sosa:ObservableProperty.

@jbkoh
Copy link
Contributor Author

jbkoh commented Sep 17, 2019

@gtfierro I am not sure what we can get from Quantities and Substances being instances. If we at some point want to instantiate Substances (e.g., ex:air1 a brick:Air.), the query and modeling pattern would be overly complicated and inconsistent with querying for other Classes like Points. Can you elaborate what it tries to solve? I read through this thread, but still don't get it.

@gtfierro
Copy link
Member

No worries! It's a bit of a subtle issue. The owl2 wiki has a nice discussion of it that I will adapt here.

Punning is a feature in OWL 2 that allows for a more flexible modeling strategy when it comes to classes and individuals (what OWL calls "instances" of a class). The OWL2 wiki has an example for eagles, but I'll adapt it for brick:Air.

In Brick 1.1.0, the term brick:Air can be used for:

  • a class: in the sense that brick:Air is the superclass of brick:Supply_Air; the organization of information
  • the class of all brick:Air: using it as a class lets us instantiate it (e.g. :room410_air a brick:Air). We're not currently using this
  • an individual: brick:Air as an individual represents the mixture of gases known colloquially as "air" belonging to the metaclass of all gasses (and transitively, all physical substances).

Punning our substances and quantities means that we can use the same terms (e.g. brick:Air and brick:Temperature) to assemble both:

  1. the hierarchy of all substances and quantities

    brick:Substance a   owl:Class .
    brick:Gas       rdfs:subClassOf     brick:Substance .
    brick:Air       rdfs:subClassOf     brick:Gas .
    brick:Supply_Air       rdfs:subClassOf     brick:Air .
  2. canonical instances of those substances and quantities that can be inferred during reasoning

    # explicit
    :ts1    a       brick:Air_Temperature_Sensor .
    
    # inferred
    :ts1    brick:measures  brick:Air .
    :ts1    brick:measures  brick:Temperature .

Without punning, the OWL restriction that instances of Air_Temperature_Sensor measure air and temperature cannot be fulfilled. OWL can't create a new instance of Air out of thin air (so to speak), so its useful to have a canonical instance to refer to. This is what the OWL restrictions below express, and is how we model it in Brick 1.1.0.

brick:Air_Temperature_Sensor a owl:Class ;
    owl:equivalentClass [ owl:intersectionOf (
					[ a owl:Restriction ;
						owl:hasValue brick:Temperature ;
						owl:onProperty brick:measures ] 
					[ a owl:Restriction ;
						owl:hasValue brick:Air ;
						owl:onProperty brick:measures ] 
				) ],

Hope that helps; it took me a while to figure this out myself.

@jbkoh
Copy link
Contributor Author

jbkoh commented Sep 18, 2019

I am fine with punning itself as we already discussed. I was curious if we need to do anything inside the model for punning. As far as I understood, we don't need anything but just Restrictions, which is already included in Brick.ttl. That's why I am confused about what you are trying to modify.

I interpreted, when you said, "Operative_Temperature is a type of Temperature" as rdf:type relationship. If you meant rdfs:subClassOf, I am with you.

@gtfierro
Copy link
Member

The key is its both rdf:type and rdfs:subClassOf. I'm making that explicit inside the Brick definition; before, you only got both statements if an entity in a Brick model actually instantiated a Sensor class

@jbkoh
Copy link
Contributor Author

jbkoh commented Sep 18, 2019

Are you saying that we need this?

brick:Operative_Temperature  a  brick:Temperature

Maybe this part wasn't clear to me in the docs you provided. I thought we just needed to define classes while we allow associating them with instances. What is the problem with the below example?

brick:Operative_Temperature   rdfs:subClassOf   brick:Temperature.
ex:sensor1  brick:measures  brick:Operative_Temperature.

@gtfierro
Copy link
Member

gtfierro commented Sep 18, 2019

Nothing is wrong with the second one: that's specifically what we are allowing. The question I'm trying to investigate is whether or not making puns explicit helps us in any way.

The following in a Brick model is a "correct" pun

brick:Operative_Temperature   rdfs:subClassOf   brick:Temperature.
ex:sensor1  brick:measures  brick:Operative_Temperature.

This means, however, that Substances + Quantities are only ever realized as individuals if there is another individual (e.g. :sensor1) of a class that has a brick:measures restriction or if brick:measures is invoked explicitly.

By explicitly including in Brick statements like

brick:Operative_Temperature  a  brick:Substance, owl:Class .
brick:Operative_Temperature rdfs:subClassOf brick:Temperature .

we might be able to make reasoning about quantity/substance instances easier. It might only be worth doing that for the tests, though, so I might drop it

Is your only objection to the current model the fact that I'm explicitly instantiating the substances and quantities as members of the parent class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants