CoordinateProperty
Coordinates might seem like ordinary properties at first glance, but they're most often NaryRelations; for example, state code standards relate three things: a country, a two-letter string, and a state. A CurriedFunction allows us to use a special kind of property, a CoordinateProperty, to relate the coordinate value to another property that relates, for example, the country to the state. The pattern generalizes to latitude, longitude, street numbers etc. hmm... age?
Consider an address like this one from the wonderful FRANK'S COMPULSIVE GUIDE TO POSTAL ADDRESSES:
JOHN DOE ACME INC 123 MAIN ST NW STE 12 ANYTOWN NY 12345
In colloquial XML, the address part might look like:
<address> <street>123 MAIN ST NW STE 12</street> <city>ANYTOWN</city></state>NY</state><zip>12345</zip> </address>
The naive analog in RDF (in NotationThree) is
[ :street "123 MAIN ST NW STE 12"; :city "ANYTOWN"; :state "NY"; :zip "12345"].
But as we learned from the InterpretationProperties pattern,
that's asking for trouble. Best to have separate subjects
to attach the city and state names to, and use a property,
say geo:inRegion
to relate them:
[ a :Address rdfs:label "123 MAIN ST NW STE 12"; geo:inRegion [ a :Zip; rdfs:label "12345"; geo:inRegion [ a :City; rdfs:label "ANYTOWN"; geo:inRegion [ a :State; rdfs:label "NY"; ]; ]; ] ].
That's not bad, but it's not as good as it could be. The point
of all those names and numbers is to uniquely identify the
state, the city, etc. down to the mailing location: there's
only one state called "NY", and there's only one street
called MAIN ST
in Anytown.
We might try...
:streetName a owl:InverseFunctionalProperty. :mainStreet :streetName "MAIN".
but in fact, there are lots of main streets; one in
just about every town in the USA. So that's not quite
right. What we want is more like:
{ :mainStreet1 geo:inRegion :anytown; :streetName "MAIN". :mainStreet2 geo:inRegion :anytown; :streetName "MAIN". } => { :mainStreet1 = :mainStreet2 }.
This is where the CurriedFunction comes in; consider
this utility schema for :[[CoordinateProperty]]
:
util:CoordinateProperty s:subClassOf owl:InverseFunctionalProperty; owl:onProperty s:domain; owl:hasValue owl:InverseFunctionalProperty.
then our postal vocabulary says:
post:street a util:CoordinateProperty. post:city a util:CoordinateProperty. post:state a util:CoordinateProperty. post:USA a post:Country.
To say that post:street
is a util:[[CoordinateProperty]]
is
to say that for every street name (or number) there is a property,
[ post:street ?NAME ]
that relates a city to the
street by that name in that city.
Then, if two parties independently describe main street using that vocabulary:
x:mainStreetP post:street "MAIN". x:anytownP post:city "ANYTOWN". x:nyP post:state "NY". x:ny x:nyP post:USA. x:anytown x:anytownP x:ny. x:mainStreet x:mainStreetP x:anytown.
and
y:mainStreetP post:street "MAIN". y:anytownP post:city "ANYTOWN". y:nyP post:state "NY". y:ny y:nyP post:USA. y:anytown y:anytownP y:ny. y:mainStreet y:mainStreetP y:anytown.
Then, by the semantics of OWL and RDFS, we have:
x:ny = y:ny. x:anytown = y:anytown. x:mainStreet = y:mainStreet.
Path shortcuts in NotationThree come in handy:
:mainStreet "MAIN"^post:street [ "ANYTOWN"^post:city [ "NY"^post:state USA ] ].
The analog for latitude and longitude is:
:lat a :CoordinateProperty. :lon a :CoordinateProperty. :earth a owl:Thing. [ is :center of :paris] 49.0^:lat [ 2.5^:lon :earth].
That is: a subject of :lat relates a point to a circle of
latitude, and a subject of :lon relates a circle of
latitude to a spherical thing such as the earth.
hmm... I think this pattern might fit better with RoleNoun if it went the
other way, i.e. using owl:[[FunctionalProperty]]
. It might be more
intuitive that way too. This orientation fits neatly with geo:inRegion
from cyc, meanwhile.
discussion with some reviewers suggests the whole "coordinate" notion is a distraction and this should be phrased in terms of multi-column keys.