Representing Time in RDF Part 4
<h2>Approach 3: Reified Relations</h2>
In this approach I reify every triple that is time-dependent. That means every triple is split out into its constituent parts which will obviously lead to an explosion of triples.
Scenario 1
In this scenario I use thing:maria to refer to Maria, and I state the fact of her being a foaf:Person as a piece of timeless information. Facts about her name are reified and time interval information is attached. The URIs thing:mariaUnmarried and thing:mariaMarried represent the reified triples holding her name before and after marriage:
@prefix bio: <http://purl.org/vocab/bio/0.1/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix time: <http://www.w3.org/2006/time#> . @prefix ex: <http://example.org/ex#> . @prefix thing: <http://example.org/thing#> .thing:maria a foaf:Person .
thing:mariaUnmarried ex:subject thing:maria ; ex:property foaf:name ; ex:value "Maria Smith" ; time:start "1867" ; time:end "1888" .
thing:mariaMarried ex:subject thing:maria ; ex:property foaf:name ; ex:value "Maria Johnson" ; time:start "1888" ; time:end "9999" .
Original file: a3s1.ttl
Facts about her name are reified using custom reification predicates, not the standard RDF ones. I do this to allow more flexibility in the use of these predicates without requiring that their subject is always an RDF statement. Potentially I could have multiple occurrences of ex:subject, ex:property or ex:value which would allow more compact descriptions to be created. For example I could have a description where multiple objects are included for the same predicate and subject.
The query in this case is straighforward and quite similar to the query for Approach 1.
prefix bio: <http://purl.org/vocab/bio/0.1/> prefix foaf: <http://xmlns.com/foaf/0.1/> prefix time: <http://www.w3.org/2006/time#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix ex: <http://example.org/ex#> prefix thing: <http://example.org/thing#>select ?name where { ?p ex:subject thing:maria . ?p ex:property foaf:name . ?p time:start ?start . ?p time:end ?end . ?p ex:value ?name . filter (xsd:integer(?start) <= 1891 && xsd:integer(?end) >= 1891) . }
Original file: a3s1.sq
I simply search for resources that represent reified triples that hold in 1891. Then I select the ex:value of the resulting resource.
Scenario 2
For simplicity I start of by treating the place name information as timeless, only reifying the information about relationships between the places:
@prefix bio: <http://purl.org/vocab/bio/0.1/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix time: <http://www.w3.org/2006/time#> . @prefix ex: <http://example.org/ex#> . @prefix thing: <http://example.org/thing#> .thing:oxfordshire a ex:County ; foaf:name "Oxfordshire" .
thing:gloucestershire a ex:County ; foaf:name "Gloucestershire" .
thing:widford a ex:Parish ; foaf:name "Widford" .
thing:widfordInGloucestershire ex:subject thing:widford ; ex:property ex:partOf ; ex:value thing:gloucestershire ; time:start "1837" ; time:end "1844" .
thing:widfordInOxfordshire ex:subject thing:widford ; ex:property ex:partOf ; ex:value thing:oxfordshire ; time:start "1844" ; time:end "9999" .
Original file: a3s2.ttl
The query is again very simple and reminiscent of Approach 1:
prefix bio: <http://purl.org/vocab/bio/0.1/> prefix foaf: <http://xmlns.com/foaf/0.1/> prefix time: <http://www.w3.org/2006/time#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix ex: <http://example.org/ex#> prefix thing: <http://example.org/thing#>select ?name where { ?p ex:subject thing:widford . ?p ex:property ex:partOf . ?p time:start ?start . ?p time:end ?end . ?p ex:value ?x . ?x foaf:name ?name filter (xsd:integer(?start) <= 1841 && xsd:integer(?end) >= 1841) . }
Original file: a3s2.sq
However, a more realistic approach would be to model the names of the places as time-dependent triples which means reifying them. I introduce some new resources thing:widfordName, thing:oxfordshireName and thing:gloucestershireName to represent the reified forms of those triples. Now the data is much more verbose:
@prefix bio: <http://purl.org/vocab/bio/0.1/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix time: <http://www.w3.org/2006/time#> . @prefix ex: <http://example.org/ex#> . @prefix thing: <http://example.org/thing#> .thing:oxfordshire a ex:County .
thing:gloucestershire a ex:County .
thing:widford a ex:Parish .
thing:widfordInGloucestershire ex:subject thing:widford ; ex:property ex:partOf ; ex:value thing:gloucestershire ; time:start "1837" ; time:end "1844" .
thing:widfordInOxfordshire ex:subject thing:widford ; ex:property ex:partOf ; ex:value thing:oxfordshire ; time:start "1844" ; time:end "9999" .
thing:widfordName ex:subject thing:widford ; ex:property foaf:name ; ex:value "Widford" ; time:start "1837" ; time:end "9999" .
thing:oxfordshireName ex:subject thing:oxfordshire ; ex:property foaf:name ; ex:value "Oxfordshire" ; time:start "1837" ; time:end "9999" .
thing:gloucestershireName ex:subject thing:gloucestershire ; ex:property foaf:name ; ex:value "Gloucestershire" ; time:start "1837" ; time:end "9999" .
Original file: a3s2a.ttl
Also the query becomes more complex:
prefix bio: <http://purl.org/vocab/bio/0.1/> prefix foaf: <http://xmlns.com/foaf/0.1/> prefix time: <http://www.w3.org/2006/time#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix ex: <http://example.org/ex#> prefix thing: <http://example.org/thing#>select ?name where { ?p ex:subject thing:widford . ?p ex:property ex:partOf . ?p time:start ?start . ?p time:end ?end . ?p ex:value ?x . filter (xsd:integer(?start) <= 1841 && xsd:integer(?end) >= 1841) .
?p2 ex:subject ?x . ?p2 ex:property foaf:name . ?p2 time:start ?start2 . ?p2 time:end ?end2 . ?p2 ex:value ?name . filter (xsd:integer(?start2) <= 1841 && xsd:integer(?end2) >= 1841) . }
Original file: a3s2a.sq
Each triple being selected requires its time interval information to be specified sepearately which is reminiscent of Approach 2
Scenario 3
Once again for simplicity I keep the place name information timeless. I introduce new resources for the reified statements about the residence of the person over time:
@prefix bio: <http://purl.org/vocab/bio/0.1/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix time: <http://www.w3.org/2006/time#> . @prefix ex: <http://example.org/ex#> . @prefix thing: <http://example.org/thing#> .thing:lymeRegis a ex:Town ; foaf:name "Lyme Regis" .
thing:charmouth a ex:Town ; foaf:name "Charmouth" .
thing:hastings a ex:Town ; foaf:name "Hastings" .
thing:anon a foaf:Person .
thing:anonInLymeRegis ex:subject thing:anon ; ex:property ex:residence ; ex:value thing:lymeRegis ; time:intervalBefore thing:anonInCharmouth ; time:intervalContains "1844" .
thing:anonInCharmouth ex:subject thing:anon ; ex:property ex:residence ; ex:value thing:charmouth ; time:intervalAfter thing:anonInLymeRegis ; time:intervalBefore thing:anonInHastings ; time:intervalContains "1871" .
thing:anonInHastings ex:subject thing:anon ; ex:property ex:residence ; ex:value thing:hastings ; time:intervalAfter thing:anonInCharmouth ; time:intervalContains "1881" .
Original file: a3s3.ttl
The query is straightforward although quite verbose. If the place name triples were also reified then this query would suddenly become much more complex:
prefix bio: <http://purl.org/vocab/bio/0.1/> prefix foaf: <http://xmlns.com/foaf/0.1/> prefix time: <http://www.w3.org/2006/time#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix ex: <http://example.org/ex#> prefix thing: <http://example.org/thing#>select ?nameBefore ?nameAfter where { ?pBefore ex:subject thing:anon . ?pBefore ex:property ex:residence . ?pBefore ex:value ?placeBefore . ?placeBefore foaf:name ?nameBefore .
?pBefore time:intervalContains ?dateBefore . filter (xsd:integer(?dateBefore) <= 1874) .
?pAfter ex:subject thing:anon . ?pAfter ex:property ex:residence . ?pAfter ex:value ?placeAfter . ?placeAfter foaf:name ?nameAfter .
?pAfter time:intervalContains ?dateAfter . filter (xsd:integer(?dateAfter) > 1874) .
?pBefore time:intervalBefore ?pAfter . }
Original file: a3s3.sq
Approach 3 Conclusions
Approach 3 avoids the domain and range problem experienced by Approach 1 where the conditions were being used with properties whose domains were foaf:Agents. In Approach 3, properties are used with the appropriate resource types when they are timeless and never actually asserted when they are time-dependent. However, this approach is tedious for large quantities of data. The semantics are all locked away behind the reified triples. Once again I don't know of any reasoners that could work with this kind of data.
This post is part 4 of a series about representing time in RDF. All posts in this series: part 1, part 2, part 3, part 4, part 5 and part 6