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

Align OWL DataProperty, YAML Attribute and add(), dot-Notation #416

Closed
urbanmatthias opened this issue Jul 1, 2020 · 8 comments · Fixed by #682
Closed

Align OWL DataProperty, YAML Attribute and add(), dot-Notation #416

urbanmatthias opened this issue Jul 1, 2020 · 8 comments · Fixed by #682
Assignees
Labels
API details 💬 discussion The idea is not mature enough to result in an implementation, and needs further discussion.
Milestone

Comments

@urbanmatthias
Copy link
Member

I am currently working on extending the pico ontology tool to install owl ontologies as well as yaml ontologies. This is important, because EMMO is currently written in owl. Of course there are some mismatches between the two ontology languages. In this issue we focus on the DataProperties of OWL vs. the Attributes of YAML.

Terminology

  • ObjectProperty: Is an OWL keyword. An ObjectProperty relates two individuals.
    Example: :matthias foaf:knows :pablo --> foaf:knows is an ObjectProperty; matthias and pablo are individuals
  • DatatypeProperty: Is an OWL keyword. A DatatypeProperty relates an individual with data.
    Example: :matthias foaf:nick "matze" --> DatatypeProperty foaf:nick relates the individual to his nickname
    :matthias foaf:nick "fletcher" --> Second nickname is allowed
  • Functional Property: An OWL keyword. It is used when only one object is allowed for each subject.
    Example: :matthias foaf:birthday "01.03.1995" --> Another triple matthias foaf:birthday "02.03.1995" would be not allowed.
  • Attributes: A YAML keyword. Basically functional DatatypeProperties.
  • Relationship: A YAML keyword. Basically non-functional ObjectProperties.

==> As you can already see here, by supporting owl we add functional ObjectProperties and non-functional DatatypeProperties, that were previously not supported.

Previous situation

Previously, we used the add() method of the CUDS API for adding Relationships (i.e. non functional ObjectProperties) and dot notation for manipulating attributes (i.e. functional DatatypeProperties).

This results in this table:
Previous behaviour:

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() not supported not supported x
dot x not supported not supported

The distinction was clear. CUDS objects were related with Relationships and therefore connected with add(). Manipulating data was always done with the dot notation. Furthermore it was possible to initialize a CUDS object by providing data values in the constructor.

Now that we have to support functional ObjectProperties and non-functional DatatypeProperties, we need to think about how we extend the API to support this.

Solution 1

Dot notation is always used for functional Properties, add() is used for non-functional properties.

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() x x
dot x x

Example: Let's assume there is a Length entity in the ontology that should have exactly one unit and one value:

:Length rdf:type owl:Class .
:Unit rdf:type owl:Class .
:hasUnit rdf:type owl:FunctionalProperty .
:hasUnit rdf:type owl:ObjectProperty .
:hasUnit rdfs:domain :Length .
:hasUnit rdf:range :Unit .
:hasValue rdf:type owl:FunctionalProperty .
:hasValue rdf:type owl:DatatypeProperty .
:hasValue rdfs:domain :Length .
:hasValue rdf:range xsd:real .

(The relationships can of course have a different name e.g. value instead of hasValue)
(This is a toy example, e.g. the domain of hasValue would not be :Length in a real example)

Then one would use dot notation only:

l = Length()
l.hasUnit = Unit()  # Or subclass of unit
l.hasValue = 12.567

If we say (as before) that everything that can be accessed via dot notation, can be provided in the constructor:

l = Length(hasUnit=Unit(), hasValue=12.567)

In the case of a non-functional data property, using foaf:nick as an example

p = Person()
p.add("peter", rel=foaf.nick)
p.add("pete", rel=foaf.nick)

# or more compact
p.add("pete", "peter", rel=foaf.nick)

Drawbacks:

  • It might be confusing that we can now assign both CUDS objects and data values via dot notation.
  • It might be confusing that we can now assign both CUDS object and data values via add().
  • The user might not know which DataProperties are defined as functional (But so far we always assumed the user knows the ontology)

Pros:

  • The API only changes only if the user updates the ontology. If he previously had hasUnit in the ontology and after the change decides that this should be functional, then he would need to change the code: Replace add() statements with dot notation.
  • Not verbose

Solution 2

Dot notation is only used for DataProperties. All Object Properties are added with add().

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() x x
dot x x

In the length example this would result in:

l = Length()
l.hasValue=12.567  # or specified in the constructor
l.add(Unit(), rel=hasUnit)
l.add(Unit(), rel=hasUnit)  # second add would not be allowed or reasoner would conclude that the two added units are identical

The nickname example would result in

p = Person(nick={"pete", "peter"})
p.nick = {"pete", "peter"}

Drawbacks:

  • It might be confusing that the user as to specify a set sometimes when using dot, and sometimes not.
  • It might be confusing that the user is allowed to call add() only once for functional ObjectProperties
  • The set might be considered "syntactic"

Pros:

  • The API only changes when the ontology changes: when the user changes an attribute to be non-functional, then he would need to provide a set of possible values (as in the nickname example)
  • It is more likely that the user knows which properties are DataProperties and which are ObjectProperties than which are Functional and which are not.

Solution 3

Use add only

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() x x x x
dot

Drawbacks:

  • too verbose
  • It might be confusing that the user is allowed to call add() only once for functional ObjectProperties
  • It might be confusing that we can now assign both CUDS object and data values via add().
  • Breaks the code: What previously was referenced by dot will now be referenced by add() and get()

Pros:

  • Only one option, no confusion when to use which method

Solution 4.1

Use add for everything, keep dot as syntactic sugar for functional properties

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() x x x x
dot x x

See examples, pros and drawbacks of Solution 1 and Solution 3

Solution 4,2

Use add for everything, keep dot as syntactic sugar for DatatypeProperties.

functional DatatypeProperty functional ObjectProperty non-functional DatatypeProperty non-functional ObjectProperty
add() x x x x
dot x x

See examples, pros and drawbacks of Solution 2 and Solution 3

More Information

Owlready uses dot notation only. Plus they encourage the user to specify a python name in the ontology, s.t. l.value = 12.567 is possible (instead of hasValue, which would be the more likely label in the ontology)
https://pythonhosted.org/Owlready/properties.html

@pablo-de-andres pablo-de-andres added API details 💬 discussion The idea is not mature enough to result in an implementation, and needs further discussion. labels Jul 1, 2020
@yoavnash
Copy link
Member

yoavnash commented Jul 1, 2020

For the first option it's written that "It might be confusing that we can now assign both CUDS object and data values via add()."
How about we introduce a new function for assigning data values? how about c.set("peter", rel=foaf.nick)?

@urbanmatthias
Copy link
Member Author

But doesn't the name set imply, that there is only one nickname?

@ahashibon ahashibon pinned this issue Jul 3, 2020
@ahashibon
Copy link
Contributor

Thank you @urbanmatthias for the very nice presentation of the issue. Before digging into the discussion we need perhaps to get some more points clear.

  1. in EMMO a quantity always has a value which is the actual value the quantity has, and if it is numerical (like real, integer, vecotr, tensor, matrix, etc) then it is always, we can sagely assume (or always render to be) functional. Hence, there is nothing against using dot notation as a convenient way of adding the value if it is numerical (this is a leaf in the tree structure).
  2. note, still under discussion in EMMO whether a value can be a function or another "language expressed entity", e.g., another EMMO entity, this does not mean that the value cannot be a function in the latter case, but that instead of using the entity value to relate the funtion to the entity, a fully fledged relation is used, like so: Length().add(SomeCUDSRepresentingAFunction(), rel=isRepresentedBy) as opposed to Length().value=SomeCUDSRepresentingAFunction().
  • the reason why we do not want value (and hence dot notation) to be used for a function or similar constructs (entity) is that the dot should hint at a leaf, and a function represented in a cUDS is simply another tree! while a number or numric is a leaf.
  1. adding multiple values to the same property, like multiple nick names to the same person can be achieved by adding multiple nickname entities, it is essentially what is the foaf example above does, add more nicknames, although the foaf seems to be too simplistic and unclear to what is an entity and what is a string
  2. It seems very safe to assume that functionalObjectProperties are not needed per se, as the cardinality is strongly related to the application, hence in some applications you want to force cardinality and in other not for the same property and entity! so I would use the cardinality constraint rather than the functional owl constraints. even then, the add seems the right thing to do.
  3. at the end of the day, the dot or add are simply two different ways to specify the same thing, except the dot is specific for cases where the relation is a value and where this value has cardinality of 1. Isn't this what you are aiming at?

@urbanmatthias
Copy link
Member Author

Update: I merged the first version that supports owl to the dev branch.
There all DataProperties are assumed to be functional and are hence accessed by dot Notation.

@urbanmatthias
Copy link
Member Author

urbanmatthias commented Jul 15, 2020

in EMMO a quantity always has a value which is the actual value the quantity has, and if it is numerical (like real, integer, vecotr, tensor, matrix, etc) then it is always, we can sagely assume (or always render to be) functional.

Then maybe it should be defined as functional. Because at the moment it is not:
image
--> See missing checkmark under characteristics.

Should we open an issue on the EMMO repo?

@yoavnash
Copy link
Member

Another suggestion for option 1 in case it becomes relevant again:
Have get to work for functional ObjectProperty and non-functional ObjectProperty, and a more informed user can use the dot-notation for his convenience.

@urbanmatthias
Copy link
Member Author

urbanmatthias commented Mar 17, 2021

I think we opted for dot notation being syntactic sugar, and otherwise we'll always use add.

That would mean we should allow stuff like:

person.add("some_nickname", rel=onto.hasNickname)

I'm not sure if this should be fixed now, because in EMMO all datatype properties are (assumed to be) functional. It will become an issue when we use OSP core with other ontologies though

@kysrpex
Copy link
Contributor

kysrpex commented Aug 20, 2021

The PR solving this is now almost ready, so I think we better continue the discussion here.

@kysrpex kysrpex added this to the v4.0.0 milestone Dec 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API details 💬 discussion The idea is not mature enough to result in an implementation, and needs further discussion.
Projects
None yet
5 participants