{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "98dd0031",
   "metadata": {},
   "source": [
    "# Skolemization"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e43516f",
   "metadata": {},
   "source": [
    "## Example 1: \"Ringo\"\n",
    "\n",
    "Example taken from \n",
    "https://github.com/RDFLib/rdflib/issues/1404"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5303b7e2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n",
      "\n",
      "<http://www.wikidata.org/entity/Q1203> foaf:knows <https://rdflib.github.io/.well-known/genid/rdflib/n7dfd882820d54ad28b8173ea7f083f31b1> .\n",
      "\n",
      "<https://rdflib.github.io/.well-known/genid/rdflib/n7dfd882820d54ad28b8173ea7f083f31b1> a foaf:Person ;\n",
      "    foaf:name \"Ringo\" .\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from rdflib import Graph\n",
    "\n",
    "\n",
    "ttl = '''\n",
    "@prefix wd: <http://www.wikidata.org/entity/> .\n",
    "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n",
    "\n",
    "wd:Q1203 foaf:knows [ a foaf:Person;\n",
    "    foaf:name \"Ringo\" ].\n",
    "    \n",
    "\n",
    "'''\n",
    "\n",
    "graph = Graph()\n",
    "graph.parse(data=ttl, format='turtle')\n",
    "skolemized = graph.skolemize()\n",
    "skolemized.namespace_manager.bind('foaf', 'http://xmlns.com/foaf/0.1/')\n",
    "print(skolemized.serialize(format='turtle'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d4608145",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n",
      "\n",
      "<http://www.wikidata.org/entity/Q1203> foaf:knows [ a foaf:Person ;\n",
      "            foaf:name \"Ringo\" ] .\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "deskolemized = skolemized.de_skolemize()\n",
    "deskolemized.namespace_manager.bind('foaf', 'http://xmlns.com/foaf/0.1/')\n",
    "print(deskolemized.serialize(format='turtle'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "708142d9",
   "metadata": {},
   "source": [
    "## Example 2: Husband"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8f945b2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "infer = True\n",
    "skolem = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8697ed1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from rdflib import Graph\n",
    "import owlrl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4b0d131c",
   "metadata": {},
   "outputs": [],
   "source": [
    "ttl = \"\"\"\n",
    "@prefix : <http://example.com/ns#> .\n",
    "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
    "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
    "\n",
    "\n",
    "# T-Box\n",
    "\n",
    ":Person a owl:Class .\n",
    "\n",
    ":Husband\n",
    "    a owl:Class ;\n",
    "    owl:equivalentClass \n",
    "        [ a owl:Restriction ;\n",
    "          owl:onProperty :has_partner ;\n",
    "          owl:someValuesFrom :Person ] .\n",
    "\n",
    ":has_partner a owl:ObjectProperty .\n",
    "\n",
    "\n",
    "# A-Box\n",
    "\n",
    ":Eve a :Person .\n",
    ":Helen a :Person.\n",
    "\n",
    "# Adam is a husband with a known partner \n",
    ":Adam\n",
    "    a :Husband ;\n",
    "    :has_partner :Eve .\n",
    "\n",
    "# Hans is a person, who has a known partner.\n",
    "# The inferencing system should classify him\n",
    "# beeing a husband. \n",
    ":Hans\n",
    "    a :Person ;\n",
    "    :has_partner :Helen .\n",
    "\n",
    "# Hugo is a husband. Thus he has a partner. \n",
    "# But we do not know the partner.\n",
    "# Q: Does the inferencing system allocate a blank node automativally?\n",
    "# A: no! \n",
    "\n",
    ":Hugo\n",
    "    a :Husband .\n",
    "\"\"\"\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ac5c0189",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#triples: 14\n"
     ]
    }
   ],
   "source": [
    "graph = Graph()\n",
    "graph.parse(data = ttl, format='ttl')\n",
    "print(f\"#triples: {len(graph)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3d366624",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "infer: True, #triples: 161\n"
     ]
    }
   ],
   "source": [
    "if infer:\n",
    "    owlrl.DeductiveClosure(owlrl.OWLRL_Semantics,\n",
    "        axiomatic_triples = False).expand(graph)\n",
    "print(f\"infer: {infer}, #triples: {len(graph)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7e49bd61",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "skolem: False \n",
      "\n",
      " @prefix : <http://example.com/ns#> .\n",
      "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
      "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n",
      "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
      "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
      "\n",
      ":Adam a _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        owl:Thing ;\n",
      "    :has_partner :Eve ;\n",
      "    owl:sameAs :Adam .\n",
      "\n",
      ":Hans a _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        :Person,\n",
      "        owl:Thing ;\n",
      "    :has_partner :Helen ;\n",
      "    owl:sameAs :Hans .\n",
      "\n",
      ":Hugo a _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        owl:Thing ;\n",
      "    owl:sameAs :Hugo .\n",
      "\n",
      "rdf:HTML a rdfs:Datatype ;\n",
      "    owl:sameAs rdf:HTML .\n",
      "\n",
      "rdf:PlainLiteral a rdfs:Datatype ;\n",
      "    owl:sameAs rdf:PlainLiteral .\n",
      "\n",
      "rdf:XMLLiteral a rdfs:Datatype ;\n",
      "    owl:sameAs rdf:XMLLiteral .\n",
      "\n",
      "rdf:langString a rdfs:Datatype ;\n",
      "    owl:sameAs rdf:langString .\n",
      "\n",
      "rdf:type owl:sameAs rdf:type .\n",
      "\n",
      "rdfs:Literal a rdfs:Datatype ;\n",
      "    owl:sameAs rdfs:Literal .\n",
      "\n",
      "rdfs:comment a owl:AnnotationProperty ;\n",
      "    owl:sameAs rdfs:comment .\n",
      "\n",
      "rdfs:isDefinedBy a owl:AnnotationProperty ;\n",
      "    owl:sameAs rdfs:isDefinedBy .\n",
      "\n",
      "rdfs:label a owl:AnnotationProperty ;\n",
      "    owl:sameAs rdfs:label .\n",
      "\n",
      "rdfs:seeAlso a owl:AnnotationProperty ;\n",
      "    owl:sameAs rdfs:seeAlso .\n",
      "\n",
      "rdfs:subClassOf owl:sameAs rdfs:subClassOf .\n",
      "\n",
      "rdfs:subPropertyOf owl:sameAs rdfs:subPropertyOf .\n",
      "\n",
      "xsd:NCName a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:NCName .\n",
      "\n",
      "xsd:NMTOKEN a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:NMTOKEN .\n",
      "\n",
      "xsd:Name a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:Name .\n",
      "\n",
      "xsd:anyURI a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:anyURI .\n",
      "\n",
      "xsd:base64Binary a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:base64Binary .\n",
      "\n",
      "xsd:boolean a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:boolean .\n",
      "\n",
      "xsd:byte a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:byte .\n",
      "\n",
      "xsd:date a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:date .\n",
      "\n",
      "xsd:dateTime a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:dateTime .\n",
      "\n",
      "xsd:dateTimeStamp a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:dateTimeStamp .\n",
      "\n",
      "xsd:decimal a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:decimal .\n",
      "\n",
      "xsd:double a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:double .\n",
      "\n",
      "xsd:float a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:float .\n",
      "\n",
      "xsd:hexBinary a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:hexBinary .\n",
      "\n",
      "xsd:int a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:int .\n",
      "\n",
      "xsd:integer a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:integer .\n",
      "\n",
      "xsd:language a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:language .\n",
      "\n",
      "xsd:long a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:long .\n",
      "\n",
      "xsd:negativeInteger a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:negativeInteger .\n",
      "\n",
      "xsd:nonNegativeInteger a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:nonNegativeInteger .\n",
      "\n",
      "xsd:nonPositiveInteger a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:nonPositiveInteger .\n",
      "\n",
      "xsd:normalizedString a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:normalizedString .\n",
      "\n",
      "xsd:positiveInteger a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:positiveInteger .\n",
      "\n",
      "xsd:short a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:short .\n",
      "\n",
      "xsd:string a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:string .\n",
      "\n",
      "xsd:time a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:time .\n",
      "\n",
      "xsd:token a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:token .\n",
      "\n",
      "xsd:unsignedByte a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:unsignedByte .\n",
      "\n",
      "xsd:unsignedInt a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:unsignedInt .\n",
      "\n",
      "xsd:unsignedLong a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:unsignedLong .\n",
      "\n",
      "xsd:unsignedShort a rdfs:Datatype ;\n",
      "    owl:sameAs xsd:unsignedShort .\n",
      "\n",
      "owl:backwardCompatibleWith a owl:AnnotationProperty ;\n",
      "    owl:sameAs owl:backwardCompatibleWith .\n",
      "\n",
      "owl:deprecated a owl:AnnotationProperty ;\n",
      "    owl:sameAs owl:deprecated .\n",
      "\n",
      "owl:equivalentClass owl:sameAs owl:equivalentClass .\n",
      "\n",
      "owl:equivalentProperty owl:sameAs owl:equivalentProperty .\n",
      "\n",
      "owl:incompatibleWith a owl:AnnotationProperty ;\n",
      "    owl:sameAs owl:incompatibleWith .\n",
      "\n",
      "owl:onProperty owl:sameAs owl:onProperty .\n",
      "\n",
      "owl:priorVersion a owl:AnnotationProperty ;\n",
      "    owl:sameAs owl:priorVersion .\n",
      "\n",
      "owl:sameAs owl:sameAs owl:sameAs .\n",
      "\n",
      "owl:someValuesFrom owl:sameAs owl:someValuesFrom .\n",
      "\n",
      "owl:versionInfo a owl:AnnotationProperty ;\n",
      "    owl:sameAs owl:versionInfo .\n",
      "\n",
      ":Eve a :Person,\n",
      "        owl:Thing ;\n",
      "    owl:sameAs :Eve .\n",
      "\n",
      ":Helen a :Person,\n",
      "        owl:Thing ;\n",
      "    owl:sameAs :Helen .\n",
      "\n",
      "owl:ObjectProperty owl:sameAs owl:ObjectProperty .\n",
      "\n",
      "owl:Restriction owl:sameAs owl:Restriction .\n",
      "\n",
      "owl:Nothing a owl:Class ;\n",
      "    rdfs:subClassOf _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        :Person,\n",
      "        owl:Nothing,\n",
      "        owl:Thing ;\n",
      "    owl:equivalentClass owl:Nothing ;\n",
      "    owl:sameAs owl:Nothing .\n",
      "\n",
      ":has_partner a owl:ObjectProperty ;\n",
      "    rdfs:subPropertyOf :has_partner ;\n",
      "    owl:equivalentProperty :has_partner ;\n",
      "    owl:sameAs :has_partner .\n",
      "\n",
      "owl:Class owl:sameAs owl:Class .\n",
      "\n",
      ":Person a owl:Class ;\n",
      "    rdfs:subClassOf :Person,\n",
      "        owl:Thing ;\n",
      "    owl:equivalentClass :Person ;\n",
      "    owl:sameAs :Person .\n",
      "\n",
      ":Husband a owl:Class ;\n",
      "    rdfs:subClassOf _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        owl:Thing ;\n",
      "    owl:equivalentClass _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband ;\n",
      "    owl:sameAs :Husband .\n",
      "\n",
      "owl:AnnotationProperty owl:sameAs owl:AnnotationProperty .\n",
      "\n",
      "owl:Thing a owl:Class ;\n",
      "    rdfs:subClassOf owl:Thing ;\n",
      "    owl:equivalentClass owl:Thing ;\n",
      "    owl:sameAs owl:Thing .\n",
      "\n",
      "rdfs:Datatype owl:sameAs rdfs:Datatype .\n",
      "\n",
      "_:n9777f20140ce4b41ac4ccd4bcf792416b1 a owl:Restriction ;\n",
      "    rdfs:subClassOf _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband,\n",
      "        owl:Thing ;\n",
      "    owl:equivalentClass _:n9777f20140ce4b41ac4ccd4bcf792416b1,\n",
      "        :Husband ;\n",
      "    owl:onProperty :has_partner ;\n",
      "    owl:sameAs _:n9777f20140ce4b41ac4ccd4bcf792416b1 ;\n",
      "    owl:someValuesFrom :Person .\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "skolemized = graph.skolemize() if skolem else graph\n",
    "\n",
    "skolemized.namespace_manager.bind('', 'http://example.com/ns#')\n",
    "skolemized.namespace_manager.bind('owl', 'http://www.w3.org/2002/07/owl#')\n",
    "\n",
    "print(\"skolem:\", skolem, \"\\n\\n\", skolemized.serialize(format='turtle'))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "019bdc1a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "http://example.com/ns#Husband http://example.com/ns#Adam http://example.com/ns#Eve\n",
      "n9777f20140ce4b41ac4ccd4bcf792416b1 http://example.com/ns#Adam http://example.com/ns#Eve\n",
      "http://www.w3.org/2002/07/owl#Thing http://example.com/ns#Adam http://example.com/ns#Eve\n",
      "http://example.com/ns#Person http://example.com/ns#Hans http://example.com/ns#Helen\n",
      "n9777f20140ce4b41ac4ccd4bcf792416b1 http://example.com/ns#Hans http://example.com/ns#Helen\n",
      "http://www.w3.org/2002/07/owl#Thing http://example.com/ns#Hans http://example.com/ns#Helen\n",
      "http://example.com/ns#Husband http://example.com/ns#Hans http://example.com/ns#Helen\n"
     ]
    }
   ],
   "source": [
    "Q = \"\"\"\n",
    "PREFIX : <http://example.com/ns#> \n",
    "PREFIX owl: <http://www.w3.org/2002/07/owl#> \n",
    "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n",
    "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n",
    "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> \n",
    "\n",
    "SELECT ?type ?a ?b \n",
    "WHERE\n",
    "  { ?a \n",
    "      a ?type;\n",
    "      :has_partner ?b .}\n",
    "\"\"\"\n",
    "\n",
    "qres = skolemized.query(Q)\n",
    "for p,q,r in qres:\n",
    "    print(p,q,r)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
