RDF and RDFS interpretations
Stronger entailment comes from fewer interpretations. RDF 1.1 Semantics adds conditions in three layers, and LeanRDF transcribes each row of each table as one field, with the section it comes from.
D-interpretations (§7.1)
Every RDF interpretation recognizes two datatypes, xsd:string and rdf:langString. LeanRDF's DInterp adds their values as abstract fields:
structure DInterp extends SimpleInterp where
langVal : String → String → Dom
IL_lang : ∀ s t, IL (.lang s t) = some (langVal s t.toLower)
strVal : String → Option Dom
IL_str : ∀ s, IL (.typed s xsd.string) = strVal s
-- plus injectivity of both
strVal is partial: an ill-typed string has no value, and a graph containing it is unsatisfiable.
RDF conditions (§8)
structure RDFConditions (I : DInterp) : Prop where
IP_iff : ∀ x, I.IP x ↔ I.InClass x (I.IS rdf.Property)
string_class : ∀ x, I.InClass x (I.IS xsd.string) ↔ ∃ s, I.strVal s = some x
langString_class : ∀ x, I.InClass x (I.IS rdf.langString) ↔ ∃ s t, x = I.langVal s t.toLower
axioms : ∀ a ∈ rdfAxioms, I.HoldsIRI a
axioms_member : ∀ n, I.HoldsIRI (rdf.member (n + 1), rdf.type, rdf.Property)
InClass x c is ⟨x, c⟩ ∈ IEXT(I(rdf:type)). A consequence used often: in an RDF interpretation every property is a resource.
RDFS conditions (§9)
The RDFS table has a row for each piece of vocabulary. A few of the sixteen fields:
structure RDFSConditions (I : DInterp) : Prop where
resource : ∀ x, I.InClass x (I.IS rdfs.Resource) ↔ I.IR x
domain : ∀ x y u v, I.IEXT (I.IS rdfs.domain) x y → I.IEXT x u v → I.InClass u y
range : ∀ x y u v, I.IEXT (I.IS rdfs.range) x y → I.IEXT x u v → I.InClass v y
subClass_ext : ∀ x y, I.SubClass x y → I.IC x ∧ I.IC y ∧ ∀ u, I.InClass u x → I.InClass u y
subClass_trans : ∀ x y z, I.SubClass x y → I.SubClass y z → I.SubClass x z
axioms : ∀ a ∈ rdfsAxioms, I.HoldsIRI a
-- … subproperties, classes, container membership, datatypes
An RDFS interpretation is a DInterp with both condition sets, and RDFS entailment quantifies over those:
def DInterp.IsRDFS (I : DInterp) : Prop := RDFConditions I ∧ RDFSConditions I
def Graph.RDFSEntails (g h : Graph) : Prop :=
∀ I : DInterp, I.IsRDFS → I.Satisfies g → I.Satisfies h
Simple ⇒ D ⇒ RDF ⇒ RDFS entailment, each a one-line theorem.
Reading the tables
Where the tables are terse, LeanRDF fixes one reading and writes it down: "transitive and reflexive on IP" is transitive and reflexive on IP; container membership properties start at rdf:_1; the value space of rdf:langString uses lowercased tags (the only reading under which §8 and §9 agree).
The core
Proofs do not need all sixteen conditions. RDFSCore collects exactly those the rules use, stated on a plain SimpleInterp, and one theorem derives it from the full conditions:
theorem DInterp.IsRDFS.toCore {I : DInterp} (h : I.IsRDFS) : RDFSCore I.toSimpleInterp
Soundness is proved against the core, which is the stronger statement: the larger the class of interpretations, the stronger a soundness theorem about all of them.