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

Document OWL sublanguage supported by the sbol_factory #5

Open
rpgoldman opened this issue Jun 2, 2021 · 15 comments
Open

Document OWL sublanguage supported by the sbol_factory #5

rpgoldman opened this issue Jun 2, 2021 · 15 comments
Labels
documentation Improvements or additions to documentation
Milestone

Comments

@rpgoldman
Copy link

Discussing experiences with other users, it seems that one needs to know what OWL constructs are and are not supported in order to effectively use the sbol_factory.

As I am working on the Containers ontology for PAML, I feel vulnerable to wasting time by encoding constraints that will either be ignored by the sbol_factory or that might cause it to malfunction.

Please expand the docs to explain what patterns to avoid, etc.

@bbartley
Copy link
Contributor

There is a very limited subset of OWL that is currently supported. Most of the supported patterns are in the following example:

opil:ParameterValue rdf:type owl:Class ;
                    rdfs:subClassOf sbol:Identified  # The ontology must "hook in" to SBOL through a subclass relationship. If this relationship isn't defined, the factory can't generate an API class

opil:hasMeasure rdf:type owl:ObjectProperty ;
                rdfs:subPropertyOf opil:compositionalProperty ;  # This is used for constructing parent-child data structures
                rdfs:domain opil:MeasureValue ;
                rdfs:range om:Measure ;
                rdfs:label "has measure" .  # The label is used to generate the Python attribute name, in this case has_measure

opil:MeasureValue rdf:type owl:Class ;
                  rdfs:subClassOf opil:ParameterValue ,
                                  [ rdf:type owl:Restriction ;
                                    owl:onProperty opil:hasMeasure ;
                                    owl:minCardinality "1"^^xsd:nonNegativeInteger ;
                                    owl:maxCardinality "1"^^xsd:nonNegativeInteger   # If this isn't provided, SBOLfactory will assume the property should be assigned a list value
                                  ] ;

@rpgoldman
Copy link
Author

@bbartley Thanks! That is really helpful. Some follow-up questions:

  1. What is done with subPropertyOf? I didn't understand what you mean by constructing parent-child data structures. Do you mean that you override the parent's property in the child class?
  2. You say that the label is used to generate the python attribute name. What happens if there is no rdfs:label property? Do you use the trailing part of the class IRI? Or is this an error case?
  3. What do you do in the following case: a class C has subclass C1 and C has property P. On objects of class C, the cardinality constraint is min cardinality 1. Class C1 adds max cardinality 1. At this point, if you make the P property of C1 be a singleton, and the P property of C be a list, things get very confusing. I was discussing this case with @jakebeal the other day: it's a reason never to represent an OWL property as a singleton-valued Python property. In the past, we have worked with a couple of libraries that tried to guess when a property could be a singleton, versus when they should be a collection value, and it has always caused problems. I strongly recommend not doing this.

@rpgoldman
Copy link
Author

Actually, on reflection, my guess about question number one does not make sense, since there can be multiple disjoint sub-properties of a single OWL property. So I am afraid I don't understand how subProperty should work at all.

@bbartley
Copy link
Contributor

  1. A compositionalProperty is a type of property that does not exist in the OWL meta-model, but does exist in SBOL and its extension languages (e.g., OPIL, PAML). See here: https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-aggregation-vs-composition/. SBOL supports both aggregated as well as compositional data structures, whereas OWL only supports the former. Since we can't express compositional relationships natively using OWL, we invented this term opil:compositionalProperty
  2. It's an error case.
  3. I don't necessarily have a good response to this. In terms of implementation, it's expedient and it works. It may be abusing OWL semantics, however.

@jakebeal
Copy link
Contributor

Note that compositionalProperty should get its namespace changed per #10

@jakebeal
Copy link
Contributor

With regards to @rpgoldman 's point 3:

What do you do in the following case: a class C has subclass C1 and C has property P. On objects of class C, the cardinality constraint is min cardinality 1. Class C1 adds max cardinality 1. At this point, if you make the P property of C1 be a singleton, and the P property of C be a list, things get very confusing

Here, I would say that since C.P has list type, so must C1.P, since otherwise it would conflict with the definition in its superclass.

The principle for reasoning: restrictions can be tightened, but not relaxed. Thus, the list/singleton distinction always gets set by the parent class.

@rpgoldman
Copy link
Author

1. A `compositionalProperty` is a type of property that does not exist in the OWL meta-model, but does exist in SBOL and its extension languages (e.g., OPIL, PAML).  See here: [visual-paradigm.com/guide/uml-unified-modeling-language/uml-aggregation-vs-composition](https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-aggregation-vs-composition/).  SBOL supports both aggregated as well as compositional data structures, whereas OWL only supports the former.  Since we can't express compositional relationships natively using OWL, we invented this term opil:compositionalProperty

Oh, I see. So a compositionalProperty is a hasPart property rather than a different kind of property? So are you saying effectively that "anything that is a measure of an entity is also a part of that entity"? Because I'm pretty sure that is what rdfs:subPropertyOf means:

The property rdfs:subPropertyOf is an instance of rdf:Property that is used to state that all resources related by one property are also related by another.

A triple of the form:

P1 rdfs:subPropertyOf P2 

states that P1 is an instance of rdf:Property, P2 is an instance of rdf:Property and P1 is a subproperty of P2. The rdfs:subPropertyOf property is transitive.

Is that what you wanted? Just from reading the name 'compositionalPropertyit seems more like what you were trying to do was to say something special about the propertyhasMeasure` itself. If that is what you want, what would be better would be something like

:isCompositionalProperty rdf:type owl:AnnotationProperty .

opil:hasMeasure rdf:type owl:ObjectProperty ;
				:isCompositionalProperty xsd:True.

An owl:AnnotationProperty has whatever semantics you want it to have, instead of taking the rdfs:subPropertyOf semantics.

3. I don't necessarily have a good response to this.  In terms of implementation, it's expedient and it works. It may be abusing OWL semantics, however.

Well, I have been involved in two programs (the BBN-led Integrated Learning and the SIFT-led Oh By The Way), and in both of them it was a real problem to narrow properties down to singletons. Because of the fact that a class could have any number of values for property P, and a subclass could have exactly one, you can end up with a translator that gives you a method p that will return either a list or a single value depending on the object it is called on, and there is no easy way to paper over that potential mismatch. Most of the time you get a list, but if you happen to call p on subclass you get a single data structure instead.

Having lists all the time can be cumbersome, but the alternative gives you creeping type uncertainty.

@rpgoldman
Copy link
Author

With regards to @rpgoldman 's point 3:

What do you do in the following case: a class C has subclass C1 and C has property P. On objects of class C, the cardinality constraint is min cardinality 1. Class C1 adds max cardinality 1. At this point, if you make the P property of C1 be a singleton, and the P property of C be a list, things get very confusing

Here, I would say that since C.P has list type, so must C1.P, since otherwise it would conflict with the definition in its superclass.

The principle for reasoning: restrictions can be tightened, but not relaxed. Thus, the list/singleton distinction always gets set by the parent class.

I think that's the correct reasoning, but I'm not sure that it's worth the additional complication in writing the translator, and maintaining code if you change your mind about cardinalities, versus just always having lists. But it's your call which is easier in the long run.

@jakebeal
Copy link
Contributor

@rpgoldman On the matter of lists vs. singletons: based on past experience, many of our users would find it hateful to use lists to interact with singleton items. The "if you happen to call p on subclass you get a single data structure instead" failure mode shouldn't be able happen with the semantics proposed here.

I think the point about rdfs:subPropertyOf is good; @bbartley, do you want to change to the annotation model?

@rpgoldman
Copy link
Author

@rpgoldman On the matter of lists vs. singletons: based on past experience, many of our users would find it hateful to use lists to interact with singleton items. The "if you happen to call p on subclass you get a single data structure instead" failure mode shouldn't be able happen with the semantics proposed here.

The semantics you propose work, I think, as long as you are willing to implement them in the compiler.

@jakebeal
Copy link
Contributor

Suggested alternate solution from @bbartley that we're aiming for: change from using owl:ObjectProperty to using sbol:CompositionalObjectProjerty, which will be a subclass of owl:ObjectProperty.

Then we don't need to say anything about either subPropertyOf or an annotation.

@rpgoldman
Copy link
Author

Suggested alternate solution from @bbartley that we're aiming for: change from using owl:ObjectProperty to using sbol:CompositionalObjectProjerty, which will be a subclass of owl:ObjectProperty.

Then we don't need to say anything about either subPropertyOf or an annotation.

That sounds right to me, but it’s above my pay grade where OWL is concerned.

Off-hand I’m surprised that this is allowed, since doesn’t subclassing property allow you second order expressive power (because you can quantify over the instances of sbol:CompositionalObjectProperty? These are deep logical waters, about which I am not informed.

@jakebeal
Copy link
Contributor

Looks like subclassing ObjectProperty is both allowed and not allowed: https://stackoverflow.com/questions/62679433/defining-a-subclass-of-owlobjectproperty-with-domains-range-constraint

@rpgoldman
Copy link
Author

I’m sorry, but I think this is a pretty strong argument for using an annotation instead. Annotations were made specifically for dealing with things ordinary OWL (which is really OWL DL) can’t. Breaking this sort of rule is likely to break standard OWL tools, so let’s not do that

@jakebeal jakebeal added this to the alpha-6 milestone Jul 2, 2021
@jakebeal
Copy link
Contributor

Recommendation for resolving both this and SynBioDex/sbol-owl3#1 from meeting of @bbartley , @jakebeal and @goksel :

Using a subproperty relationship for parent/child relationships. This, given e.g., A paml:node B you can also correctly conclude A [hasChild] B. This avoids the problems with trying to subclass object property. You can also trace these relationships in order to determine closure blocks if you want.

The name to be used for the property is still not determined. Possibilities include:

  • sbol:hasChild
  • sbol:hasChildObject
  • sbol:compositionalProperty
  • sbol:compositeAggregation
  • sbol:hasPart
  • sbol:isComposedOf
  • sbol:comprises

@jakebeal jakebeal removed this from the alpha-6 milestone Sep 1, 2021
@jakebeal jakebeal added this to the 1.0 milestone Oct 28, 2021
@jakebeal jakebeal added the documentation Improvements or additions to documentation label Oct 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants