In recent work I've been doing I've noticed a common problem is how to define measurements such as "3 kilometers" or "40 miles per hour". There are some sophisticated vocabularies out there that address this problem. However, for some projects what is required isn't a huge vocabulary that can address every possible use case but a small and simple vocabulary to address the majority of them. The ontology I've created here is an attempt to fill that niche.
There are two top level classes: Measurement and Unit. The Unit class has subclasses: DistanceUnit, TimeUnit, and WeightUnit. The instances of Unit are individuals such as Mile, Hour, and Kilogram. Of course this can easily be extended with for example currency units such as Dollars. The Measurement class has subclasses SingleUnitMeasurement, DoubleUnitMeasurement, and TripleUnitMeasurement for measurements in one, two and three dimensions respectively. E.g., instances of SingleUnitMeasurement are Miles10, Hours1, and Kilograms20. Example instances of DoubleUnitMeasurement and TripleUnitMeasurement are Mph20 (speed) and Kpsps10 (acceleration). I put the number after the name of each individual so that in a list of individuals all measurements with the same units will be viewed together.
The Measurement class has two data properties: hasMeasuredValue is an xsd:decimal with the actual value and measuredAtTime is an xsd:dateTime that optionally records the time the measurement was taken. The object properties are hasUnit1, hasUnit2, and hasUnit3 which define the Unit for each Measurement. The other properties are greaterThan, lessThan, greaterThanOrEqualTo, equalTo, etc. These define an order for Measurement individuals that have the same number of dimensions and kind of units. The equalTo property is of course symmetric (each Measurement is equalTo itself) and the greaterThan and lessThan properties are inverses and transitive. Because the properties are transitive it is only required to define an order in one direction and the inverse property will automatically be inferred.
I have also defined some transformation rules that convert between different units. The two that I have in the current version are transformations between Kilometers and Miles and between kph and mph. I think it would be very straight forward for users to follow the pattern of the existing rules (starting by cloning the relevant rule in the SWRLTab) to add new units and new transformations.
One of the drawbacks of this version is that many transformation rules are required. I have an idea for a revised design that will reduce the required number of transformations but I'm not sure if/when I will implement that and I think the current version might be useful to others as it is. I hope people find some value from it. As always please feel free to contact me with comments or questions.
Update from 4/13/2021
I have created a new version of the ontology that addresses the problem I described with the first version. I do this by having a canonical unit for each measurement. E.g., the canonical unit for distance is meters. The canonical unit for each type of measure is stored on the class itself by utilizing punning. For example, in the SWRL rules that convert different measurements such as inches and miles to meters there is the expression:
I.e., these rules will only fire if the hasCanonicalUnit for the DistanceMeasurement class is equal to the instance of unit: Meter. To change the canonical unit one merely needs to
Change the value on the punned individual for the measurement class to the new canonical unit. E.g., if you wanted to change the canonical unit for distance to kilometers, you would change the value from Meter to Kilometer
Clone each of the existing SWRL rules and change this expression to test for the new canonical unit. You could also simply edit each rule but I would suggest cloning them. This way you still have the old rules if you decide to go back to that canonical unit.
Change the conversion factor to the appropriate number in each of the cloned or edited rules.
For example, the current rule to transform FeetMeasurement to meters is:
hasCanonicalUnit(DistanceMeasurement, Meter) ^ DistanceMeasurement(?m1) ^ hasUnit1(?m1, Foot) ^ hasMeasuredValue(?m1, ?v1) ^ swrlb:multiply(?cv, ?v1, 0.3048) -> sm:hasCanonicalValue(?m1, ?cv)
To change the canonical unit to kilometers one would edit the hasCanonicalUnit value for DistanceMeasurement, clone this rule, and then edit the cloned rule as follows (the edited parts are in bold):
hasCanonicalUnit(DistanceMeasurement, Kilometer) ^ DistanceMeasurement(?m1) ^ hasUnit1(?m1, Foot) ^ hasMeasuredValue(?m1, ?v1) ^ swrlb:multiply(?cv, ?v1, 0.0003048) -> sm:hasCanonicalValue(?m1, ?cv)
I have also created a GitHub repository for the ontology so that if people use it they will be notified of future changes. It can be found here: https://github.com/mdebellis/SIMON-A-Simple-Measurement-Vocabulary
One other minor change: the equalTo property is no longer symmetric. I didn't realize but making a property symmetric causes the reasoner to infer that its domain and range are owl:Thing. This caused problems for the Disjoint axioms I had (e.g., that a Measurement is disjoint with a Unit). In any case it wasn't needed as the test for equality also tests to see if a measurement is equal to itself.