Retail products -- basic, enumerated and multidimensional quality patterns
gUFO treats a quality (a gemstone's mass, a painting's color) as a first-class individual that inheres in the thing it characterizes, rather than as a bare literal attribute -- this is what lets you attach further information to the quality itself (when it changed, what its value means in different scales) and is called reification. This example walks through the three patterns the gUFO usage guide offers for giving a reified quality a value, from simplest to most expressive, on three different products.
A small retailer sells gemstones (characterized by mass), t-shirts (characterized by size) and paintings (characterized by color) -- three products, three qualities, three ways of recording a value.
Gemstone1's mass)The simplest pattern: the quality is a reified individual, related to its bearer via a sub-property of
gufo:inheresIn, and given a value via a sub-property of the datatype property
gufo:hasQualityValue:
:Mass rdfs:subClassOf gufo:Quality .
:massOf rdfs:subPropertyOf gufo:inheresIn ;
rdfs:domain :Mass ; rdfs:range :Gemstone .
:massInGrams rdfs:subPropertyOf gufo:hasQualityValue ;
rdfs:domain :Mass ; rdfs:range xsd:double .
:Gemstone1Mass a :Mass ;
:massOf :Gemstone1 ;
:massInGrams "4.5"^^xsd:double .
The ontology also restricts :Mass to inhere in exactly one gemstone
(owl:qualifiedCardinality "1" on gufo:inheresIn) -- a good habit for any quality
type once its bearer's class is known, since gUFO itself leaves gufo:inheresIn
unconstrained.
Use this pattern whenever a plain number (or string, date, ...) is all a quality value needs to be.
TShirt1's size)A shirt size is not naturally a number: "S", "M", "L", "XL" is a closed, ordered set with no obvious
numeric encoding worth committing to. Instead of a literal, the quality is given an individual drawn from a
class of gufo:QualityValue, restricted by owl:oneOf to exactly those four
individuals:
:ShirtSize rdfs:subClassOf gufo:QualityValue ;
owl:equivalentClass [ a owl:Class ; owl:oneOf ( :S :M :L :XL ) ] .
:Size rdfs:subClassOf gufo:Quality .
:sizeOf rdfs:subPropertyOf gufo:inheresIn ;
rdfs:domain :Size ; rdfs:range :TShirt .
:hasSizeValue rdfs:subPropertyOf gufo:hasReifiedQualityValue ;
rdfs:domain :Size ; rdfs:range :ShirtSize .
:TShirt1Size a :Size ;
:sizeOf :TShirt1 ;
:hasSizeValue :M .
The object property gufo:hasReifiedQualityValue (rather than the datatype property
gufo:hasQualityValue from pattern 1) is gUFO's marker that the value itself is a reified
individual, not a literal.
Painting1's color)Color needs more than one number at once -- a point in a 3-D space, not a single scalar or an item from a
closed list. The value is again a gufo:QualityValue individual (this time not restricted by
owl:oneOf, since the space of RGB triples is not enumerable), but now it carries its own
datatype properties, each a sub-property of gufo:hasValueComponent, one per dimension:
:ColorValueInRGB rdfs:subClassOf gufo:QualityValue .
:hasRedValueComponent rdfs:subPropertyOf gufo:hasValueComponent ;
rdfs:domain :ColorValueInRGB ; rdfs:range xsd:nonNegativeInteger .
:hasGreenValueComponent rdfs:subPropertyOf gufo:hasValueComponent ; ... .
:hasBlueValueComponent rdfs:subPropertyOf gufo:hasValueComponent ; ... .
:Color rdfs:subClassOf gufo:Quality .
:hasColorValueInRGB rdfs:subPropertyOf gufo:hasReifiedQualityValue ;
rdfs:domain :Color ; rdfs:range :ColorValueInRGB .
:Painting1Color a :Color ;
:colorOf :Painting1 ;
:hasColorValueInRGB [ a :ColorValueInRGB ;
:hasRedValueComponent "0"^^xsd:nonNegativeInteger ;
:hasGreenValueComponent "47"^^xsd:nonNegativeInteger ;
:hasBlueValueComponent "167"^^xsd:nonNegativeInteger ] .
Because the value is reified, the same color could, without touching :Painting1Color's
identity, also be given a value in a different space -- e.g. a CMYK quadruple via a second
hasColorValueInCMYK property -- something a bare literal could never support cleanly.
| Value shape | Use | Example here |
|---|---|---|
| A single number, string, date, ... | gufo:hasQualityValue (datatype property) + a literal | Mass in grams |
| One of a fixed, enumerable set | gufo:hasReifiedQualityValue + owl:oneOf | Shirt size |
| A point in a multidimensional space | gufo:hasReifiedQualityValue + gufo:hasValueComponent per dimension | RGB color |
All three qualities remain, throughout, ordinary gufo:ConcreteIndividuals: nothing stops you
from also tracking, e.g., when a quality's value last changed, using the situation-based pattern in
example 6.
See ontology.ttl for the complete file.
gufo.ttl + ontology.ttl is
consistent and satisfiable, including the qualified cardinality restriction on :Mass.cd examples/tests
.venv/bin/pytest -v -k qualities