---
jupytext:
  formats: md:myst
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
    jupytext_version: 1.14.1
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
---

# 3-Star to 5-Star: Schnitzel vom jungen Rind


Diese Seite: Demo, wie man von einer nicht normalisierten CSV-Datei (LOD 3-Star) zu einem ontologiebasierten RDF-Graphern (LOD 5-Star) und wieder zurück zu einem Tabellen-View kommt -- unter Einbeziehung von OWL2-RL Inferencing, in diesem Fall einer ontologiebasierten Klassifizierung von Instanzen.


## Tabelle einlesen

In diesem Fall liegt die Tabelle als CSV-Datei vor.  Aber genau
genommen interessiert uns nicht, in welchem konkreten Format (CSV, Excel, JSON, etc) unsere
Tabelle tatsächlich vorliegt: Solange wir unsere Daten mit Pandas
einlesen und in ein Pandas DataFrame überführen können, sind wir zufrieden.

```{code-cell} ipython3
import pandas as pd
example = "Schnitzel_vom_Jungrind"
df = pd.read_csv(f"../sheets/{example}.csv", 
                            dtype=str, delimiter= ';')
df.fillna(value="", inplace=True)
df
```

Diskussion: Wir sehen, dass die Tabelle nicht normalisiert ist.
* Offensichtlich bezieht sich die Spalte `hat_Alter` auf das *Tier_1* (aus Spalte `hat_Herkunft`), von dem das *Schnitzel_1* stammt, und nicht auf das *Schnitzel_1* (Spalte `Schnitzel`) selbst.
* Unklar ist, ob sich die Spalte `Altersgruppe` auf die Spalte `hat_Herkunft` oder die Spalte `hat_Alter` bezieht.

(ABBILDUNG möglich: Tabellen-Bezüge mit Pfeilen visualisieren)

## GenDIfS Mindmap einlesen, compilieren

![](../../images/Schnitzel_vom_Jungrind.png)

```{code-cell} ipython3
import sys
sys.path.append('../py/')
from gd06 import GenDifS_Map
```

```{code-cell} ipython3
backup_mindmap = False
update_mindmap = False

# Mindmap und Sheet einlesen
o = GenDifS_Map(f"../mm/{example}.mm", # Mindmap
       sheet_df = df,         # das oben eingelesene DataFrame
       pattern = ['ALL', 'owl', 'a-box', 'owl-classify'],
       verbose = 1)

# Lexikalische Analyse, Parser, OWL-Code erzeugen
o.compile()
```

Zur Kontrolle: Beim Compilieren wurde die Mindmap so interpretiert:

```{code-cell} ipython3
o.display_markdown()
```

Die Mindmap kann mit jedem Mindmap-Tool editiert werden, das das (einfache XML-) Format `*.mm` unterstützt. Wir verwenden `freeplane`. Als Feednack an Mindmap-Nutzer kann die interpretierte Mindmap wieder in zurückgeschrieben werden:

```{code-cell} ipython3
if update_mindmap:
    update_mindmap_filename = f"../mm/{example}.mm"
    o.mindmap.write(update_mindmap_filename,pretty_print=True)
    print(f"updated mindmap {update_mindmap_filename}")
```

## ttl Code ohne Inferencing

In Rahmen dieses Protototypen erzeugt der Compiler Turtle (ttl-) Code direkt als String (`print(o.ttl_code)`):

```{code-cell} ipython3
print(o.ttl_code)

# bei Bedarf im Dateisystem speichern
with open(f"../ttl/{example}_mm.ttl", "w") as file:
    file.write(o.ttl_code)
```

Wir lesen diesen Code mit der Standard-Bibliothek `librdf` ein und erhalten den RDF-Graphen `o.rdflib_graph`. Wenn man diesen Graphen wieder im Format ttl serislisiert sieht man, dass die Tripel anders zusammengefasst sind und alles insgesamt „aufgeräumter“ aussieht. 

Die Methode `o.select_molecules()` dient dazu, in der ttl-Fassung eines Graphen nach Text-Absätzen zu suchen, in denen einer von mehreren Strings vorkommt. Zweck ist die gezielte Inspektion eines Graphen nach bestimmten Klassen oder Instanzen.

## Schnitzel_1 ohne Inferencing

Alles über *Schnitzel_1* und/oder *Tier_1* im Graphen `o.rdflib_graph`:

```{code-cell} ipython3
print(o.select_molecules(o.rdflib_graph,
  ["sheet:Schnitzel_1", "sheet:Tier_1", "sheet:210_Tage" ]))
```

Vergleicht man diesen ttl-Code mit der CVS-Tabelle oben sieht man, wie die entsprechenden Informationen zu *Schnitzel_1* nach ttl übersetzt wurden: Der vollständige RDF-Graph `o.rdflib_graph` enthält außer der RDF-Fassung unserer Tabelle -- der sog. Assertion-Box, A-Box -- auch die entsprechenden teilweise axiomatisierten Klassen, die sog. Terminology-Box, T-Box. Damit liegt unsere Tabelle als vollwertiges *LOD 5-Star* Datenmodell vor.

Wir sehen:
* *Schnitzel_1* stammt von *Tier_1*
* *Tier 1*
  * wurde als *Rind* deklariert (aber nicht als Kalb!)
  * ist *210_Tage* alt

Aufgrund dieser Informationen kann ein Mensch ableiten, dass Schnitzel_1 ein Kalbsschnitzel ist -- aber unmittelbar aus den Daten ablesen kann man das nicht!


## Schnitzel_1 mit Inferencing

Liegen Daten einmal als RDF-Graph vor, lassen sich bei Vorhandensein einer geeigneten Ontologie (hier in Form einer T-Box) dann auch formal-logische Schlussfolgerungen ableiten. Die Methode `o.owlrl()` stößt den Reasoner `owlrl` an, der das OWL-Profil `OWL2-RL` implementiert.

```{code-cell} ipython3
o.owlrl()
print(o.select_molecules(o.owlrl_graph,
            ["sheet:Schnitzel_1", "sheet:Tier_1"]))
```

Wir sehen hier, dass durch das Inferencing korrekt klassifiziert wurde:
* *Tier_1* aufgrund seines Alters als *Kalb*
* *Schnitzel_1* aufgrund seiner Herkunft als *Kalbschnitzel*.

Ist das KI? JA, und zwar eindeutig gemäß [EU Entwurf AI Act](https://eur-lex.europa.eu/legal-content/DE/TXT/HTML/?uri=CELEX:52021PC0206), Anhang I: *Techniken und Konzepte der Künstlichen Intellizenz* gemäß Artikel 3 Absatz 1:

> b) Logik- und wissensgestützte Konzepte, einschließlich Wissensrepräsentation, induktiver (logischer) Programmierung, Wissensgrundlagen, Inferenz- und Deduktionsmaschinen, (symbolischer) Schlussfolgerungs- und Expertensysteme;

+++

## SPARQL

Der RDF-Graph lässt sich mit SPARQ abfragen.

```{code-cell} ipython3
Q = """
PREFIX ex: <http://example.net/namespace/ex#> 
PREFIX sheet: <http://example.net/namespace/sheet#> 
PREFIX : <http://example.net/namespace/default#> 
PREFIX owl: <http://www.w3.org/2002/07/owl#> 
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX xml: <http://www.w3.org/XML/1998/namespace> 
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 


SELECT ?a?b ?c
WHERE
  { ?a 
      a :Kalbschnitzel .}
"""

qres = o.owlrl_graph.query(Q)
for p,q,r in qres:
    print(p,q,r)
```
