{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook documents how to solve the famous [zebra puzzle](http://en.wikipedia.org/wiki/Zebra_puzzle) by A. Einstein with the help of semantic web tools for python.\n", "\n", "\n", "It is based on theses Links/Projects\n", "\n", "- https://pythonhosted.org/Owlready2/index.html\n", "- https://github.com/RDFLib/OWL-RL/issues/3 \"Solving Einstein's riddle (zebra puzzle\"\n", " - Linked owl-files:\n", " - https://github.com/RDFLib/OWL-RL/files/1533408/einsteins_riddle.owl.txt ← works\n", " - created by [D. Ponomaryov](https://persons.iis.nsk.su/en/ponom/ontologies)\n", "\n", "For installation I did:\n", "\n", "```bash\n", "pip install owlready\n", "``` \n", "\n", "Note there is also https://github.com/RDFLib/OWL-RL/files/1533409/zebra.n3.txt but the N3-Format is not supported by Owlready.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import owlready2 as owl2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Solution\n", "\n", "Assumption: ontology file has been downloaded to `./ontology_data/`. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "data_path = \"ontology_data\"\n", "path1 = os.path.join(data_path, \"einsteins_riddle.owl.txt\")\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "classes (concepts):\n", " [owl.Nothing, einsteins_riddle.owl.txt.Beverage, einsteins_riddle.owl.txt.Man, einsteins_riddle.owl.txt.Color, einsteins_riddle.owl.txt.House, einsteins_riddle.owl.txt.Pet, einsteins_riddle.owl.txt.Cigarette] \n", "\n", "\n", "properties (roles):\n", " [einsteins_riddle.owl.txt.drinks, einsteins_riddle.owl.txt.has_color, einsteins_riddle.owl.txt.lives_in, einsteins_riddle.owl.txt.owns, einsteins_riddle.owl.txt.right_to, einsteins_riddle.owl.txt.smokes, 1.1.description, 1.1.date, 1.1.creator] \n", "\n", "\n", "individuals:\n", " [einsteins_riddle.owl.txt.orange_juice, einsteins_riddle.owl.txt.tea, einsteins_riddle.owl.txt.water, einsteins_riddle.owl.txt.coffee, einsteins_riddle.owl.txt.milk, einsteins_riddle.owl.txt.Kools, einsteins_riddle.owl.txt.Lucky_Strike, einsteins_riddle.owl.txt.Parliaments, einsteins_riddle.owl.txt.Chesterfields, einsteins_riddle.owl.txt.Old_Gold, einsteins_riddle.owl.txt.green, einsteins_riddle.owl.txt.red, einsteins_riddle.owl.txt.blue, einsteins_riddle.owl.txt.yellow, einsteins_riddle.owl.txt.ivory, einsteins_riddle.owl.txt.house_2, einsteins_riddle.owl.txt.house_3, einsteins_riddle.owl.txt.house_1, einsteins_riddle.owl.txt.house_4, einsteins_riddle.owl.txt.house_5, einsteins_riddle.owl.txt.Ukrainian, einsteins_riddle.owl.txt.Spaniard, einsteins_riddle.owl.txt.Norwegian, einsteins_riddle.owl.txt.Englishman, einsteins_riddle.owl.txt.Japanese, einsteins_riddle.owl.txt.zebra, einsteins_riddle.owl.txt.horse, einsteins_riddle.owl.txt.snails, einsteins_riddle.owl.txt.dog, einsteins_riddle.owl.txt.fox]\n" ] } ], "source": [ "# get an overview what is inside the Ontology\n", "onto = owl2.get_ontology(path1).load()\n", "print(\"classes (concepts):\\n\", list(onto.classes()), \"\\n\"*2)\n", "print(\"properties (roles):\\n\", list(onto.properties()), \"\\n\"*2)\n", "print(\"individuals:\\n\", list(onto.individuals()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Relations before calling the reasoner" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[(einsteins_riddle.owl.txt.Norwegian, einsteins_riddle.owl.txt.house_1)]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(onto.lives_in.get_relations())" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[(einsteins_riddle.owl.txt.Spaniard, einsteins_riddle.owl.txt.dog)]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(onto.owns.get_relations())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calling the reasoner and inspect relations again" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 30.8 ms, sys: 4.35 ms, total: 35.2 ms\n", "Wall time: 4.68 s\n" ] } ], "source": [ "%time owl2.sync_reasoner_pellet(infer_property_values=True, infer_data_property_values=True, debug=0)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(einsteins_riddle.owl.txt.Norwegian, einsteins_riddle.owl.txt.house_1), (einsteins_riddle.owl.txt.Englishman, einsteins_riddle.owl.txt.house_3), (einsteins_riddle.owl.txt.Japanese, einsteins_riddle.owl.txt.house_5), (einsteins_riddle.owl.txt.Ukrainian, einsteins_riddle.owl.txt.house_2), (einsteins_riddle.owl.txt.Spaniard, einsteins_riddle.owl.txt.house_4)]\n" ] } ], "source": [ "rels = list(onto.lives_in.get_relations())\n", "print(rels)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(einsteins_riddle.owl.txt.Spaniard, einsteins_riddle.owl.txt.dog), (einsteins_riddle.owl.txt.Englishman, einsteins_riddle.owl.txt.snails), (einsteins_riddle.owl.txt.Japanese, einsteins_riddle.owl.txt.zebra), (einsteins_riddle.owl.txt.Norwegian, einsteins_riddle.owl.txt.fox), (einsteins_riddle.owl.txt.Ukrainian, einsteins_riddle.owl.txt.horse)]\n" ] } ], "source": [ "rels = list(onto.owns.get_relations())\n", "print(rels)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "n.Spaniard.owns: n.dog\n", "n.Englishman.owns: n.snails\n", "n.Japanese.owns: n.zebra\n", "n.Norwegian.owns: n.fox\n", "n.Ukrainian.owns: n.horse\n" ] } ], "source": [ "for r in rels:\n", " print(f\"n.{r[0].name}.owns: n.{r[1].name}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Conclusion\n", "\n", "The puzzle could be solved easily by the reasoner\n", "\n", "---\n", "\n", "Note: This Puzzle is also an example of [yamlpyowl](https://github.com/cknoll/yamlpyowl) – an experimental package to represent OWL-Ontologies in YAML:\n", "\n", "\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.8.6" } }, "nbformat": 4, "nbformat_minor": 2 }