Open rpgoldman opened 3 years ago
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
] ;
@bbartley Thanks! That is really helpful. Some follow-up questions:
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?rdfs:label
property? Do you use the trailing part of the class IRI? Or is this an error case?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.
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:compositionalPropertyNote that compositionalProperty
should get its namespace changed per #10
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.
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 ofrdf: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 ofrdf:Property
,P2
is an instance ofrdf:Property
andP1
is a subproperty ofP2
. Therdfs: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 property
hasMeasure` 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.
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.
@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 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.
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.
Suggested alternate solution from @bbartley that we're aiming for: change from using
owl:ObjectProperty
to usingsbol:CompositionalObjectProjerty
, which will be a subclass ofowl: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.
Looks like subclassing ObjectProperty is both allowed and not allowed: https://stackoverflow.com/questions/62679433/defining-a-subclass-of-owlobjectproperty-with-domains-range-constraint
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
Recommendation for resolving both this and https://github.com/SynBioDex/sbol-owl3/issues/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
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.