---
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
---

# Milch (DE)


## Ausgangspunkt

Die maßgebliche Motivation für GenDifS ist das Konzept der `skos:Collection`-Klasse, veranschaulicht in dem Milch-Beispiel aus dem SKOS-Primer [4 Advanced SKOS: When KOSs are not Simple Anymore > 4.1 Collections of Concepts](https://www.w3.org/TR/skos-primer/#seccollections):

    milk
      <milk by source animal>
        cow milk
        goat milk
        buffalo milk


```{figure} ../images/akwi2022_Milch-Beispiel.png
---
name: fig-milch-beispiel
alt: Milch > BY Fleisch_hat_Herkunft SOME Tier >> Kuhmilch >>> SOME Kuh
---
Beispiel Milch
```


## ttl dieses Beispiels erzeugen

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

```{code-cell} ipython3
mm = "Milch_DE"
o = GenDifS_Map(f"../mm/{mm}.mm")
o.compile()
```

```{code-cell} ipython3
# export raw GenDifS turtle
with open(f"../ttl/{mm}_mm.ttl", "w") as file:
    file.write(o.ttl_code)

#export rdflib graph: quality checked!
len(o.rdflib_graph.serialize(destination=f"../ttl/{mm}_rdflb.ttl"))
```

Inferencing mit OWLRL:

```{code-cell} ipython3
o.owlrl()
len(o.owlrl_graph.serialize(destination=f"../ttl/{mm}_owlrl.ttl"))
```

## Erklärungen

Anschauliche Erklärung: Offensichtlich sind in diesem Beispiel zwei parallele Teilmengen-Beziehungen enthalten. Die erste, in **Fettdruck** wiedergegebene Beziehung besteht zwischen den Hauptklassen Milch und Kuhmilch und spannt insgesamt den für Mindmaps typischen Primärbaum auf:

```
:Kuhmilch
   rdfs:subClassOf :Milch .
```

Mit diesem Baum ist aber auch eine zweite, in der Abbildung in unterstrichenem *Kursivdruck* wiedergegebene Beziehung zwischen charakterisierenden Sekundärbaum  eng verflochten:

```
:Kuh
   rdfs:subClassOf :Tier .
```

In GenDifS werden zwei wie hier zusammengehörenden Bäume ineinander verflochten modelliert. Dieses Syntax-Detail von GenDifS entspringt der Beobachtung, dass wir oft einen Sekundärbaum verwenden, um einen Primärbaum zu modellieren.

In Protegé sieht man, dass hier (mindestens) die folgenden zwei Begriffsbäume enthalten sind:


```{figure} ../images/Milch_DE_Protege.png
---
name: fig-milch-beispiel
alt: Milch > BY Fleisch_hat_Herkunft SOME Tier >> Kuhmilch >>> SOME Kuh
---
Beispiel Milch in Protegé
```

<!-- akwi2022_Milch-Beispiel.png -->

+++

## T-Box: OWL-Klassen und -Inferencing


Wir betrachten den Satz:

    Kuhmilch ist eine Milch, die von Rindern kommt.

In diesem Satz sind diese Informationen enthalten:

* `Kuhmilch`: Darum geht es im folgenden; Subjekt
* `ist`: die Beziehung zum Oberbegriff ist (hier) eine Teilmengenbeziehung
* `eine Milch ...`: erste Chrakterisierung von Kuhmilch, hier durch Kennzeichnung als Teilmenge des Oberbegriffs `Milch`
* `eine Milch, die ...`: Charakterisierung einer speziellen Teilklasse von `Milch` durch eine zusätzliche chrakterisierende Eigenschaft
* `von ... kommt.`: chrakteristisches Attribut ist die *Herkunft* (und nicht z.B. der Fettgehalt)
* `... Rindern ...`: der Wert des chrakteristischen Attributs Herkunft sind Rinder.


An der Formalisierung beteiligte Mengen:

**Menge 1: alle Dinge, die eine Milch sind**

```
:Milch
   a owl:Class ;
   rdfs:subClassOf :topConcept .
```

**Menge 2: alle Dinge, die als Herkunft "Kuh" haben**

```
:SOME_166726759_restriction
   a owl:Class ;
   rdfs:label "BY hat_Herkunft BYSOME Tier SOME Kuh" ;
   rdfs:subClassOf :gendifs_restrictions ;
   owl:equivalentClass [ a owl:Restriction ;
      owl:onProperty :hat_Herkunft ;
      owl:someValuesFrom :Kuh ] .
```

**Menge 3: alle Dinge, die eine Kuhmilch sind**

```
:Kuhmilch
   a owl:Class ;
```

Die Mengen 1-3 stehen bis jetzt völlig nebeneinander. Um Inferencing zu ermöglichen, beschreiben wir ihren Zusammenhang mit Axiomen.

+++

### Aufwärts-Inferencing
    
Um ein relativ triviales Inferencing zu ermöglichen, fügen wir ein Subklassen-Axiom hinzu:

**Menge 3 ist eine Teilmenge von Menge 1**

```
:Kuhmilch
   rdfs:subClassOf :Milch .
```

Aufgrund dieser Aussage wird ein Reasoner dann, wenn ein Ding X Element der Menge 3: Kuhmilch ist, dieses Ding auch als Element der Menge 1: Milch klassifizieren.

Weil hier von einer Teilmenge auf die übergeordnete Menge geschlossen wird, wollen wir dieses Inferencing "aufwärts" nennen.

+++

### Abwärts-Inferencing

Um ein Ding anhand seiner Eigenschaften genauer klassifizieren zu können, benötigen wir erstens eine weitere Menge:

**Menge 4 = Schnittmenge von Menge 1 und Menge 2:** Alle Dinge, die eine Milch sind, UND die als Herkunft Kuh haben.

```
:SOME_166726759_intersection
   a owl:Class ;
   rdfs:label "(BY hat_Herkunft BYSOME Tier SOME Kuh) INTERSECT Milch" ;
   owl:equivalentClass [ a owl:Class ;
      owl:intersectionOf (
          :SOME_166726759_restriction
          :Milch ) ] .
```

Und um das Inferencing letztlich möglich zu machen, fügen wir zweitens noch eine weiteres Axiom hinzu, mit dem Menge 4 als Teilmenge von Menge 3 definiert wird: 

**Alle Dinge, die aus Menge 4 sind, sind automatisch auch enthalten in Menge 3**

```
:SOME_166726759_intersection
   rdfs:subClassOf :Kuhmilch .
```

Indem wir die Schnittmenge von Menge 1 und 2 als Teilmenge von Menge 3 definieren, wird jetzt das gesuchte Inferencing unterstützt, das uns die Klassifiation erlaubt: Gegeben sei ein Ding X, von dem wir wissen,

* dass es eine Milch ist: X ist Element von Menge 1;
* dass es von einer Kuh stammt: X ist gleichzeitig auch Element von Menge 2.

Aufgrund dieser Angaben wird der Reasoner X auch als Element der Menge 4 klassifizieren. Und da Menge 4 als eine Teilmenge von Menge 3 definiert wurde, wird der Reasoner dann X ebenfalls als Element der Menge 3 klassifizieren: Damit wäre der Klassifikationsschritt Milch + Herkunft Kuh = Kuhmilch durchgeführt!

Formalisierung des Abwärts-Inferencings in Mengenschreibweise:

    Kuhmilch ⊇ {x | Milch(x) ∧ ∃y[hat_Herkunft(x,y) ∧ Kuh(y)] }

Formalisierung in First Order Logic (FOL): 

    ∀x[Kuhmilch(x) ← Milch(x) ∧ ∃y[hat_Herkunft(x,y) ∧ Kuh(y)]

Formalisierung in Description Logic (DL):

    Kuhmilch ⊇ X
    X == Milch ∧ ∃ hat_Herkunft.Kuh

(Wir haben hier `X` als Abkürzung für `:Milch_AND_:hat_Herkunft_SOME_:Kuh` verwendet.)

+++

## A-Box


In GenDifS wird eine Ontologie abstrakt in einer Mindmap-basierten Sprache dargestellt. Deshalb ist es nötig, die Mindmap in mindestens eine, und möglich, die Mindmap in mehr als eine Ontologiesprache zu übesetzen.

Tatsächlich übersetzen wir einen einzigen Knoten in 3 verschiedene Objekte, die wir per Namespace unterscheiden:


```
@prefix : <http://mm2ttl.net/namespace/default#> .
@prefix cpt: <http://mm2ttl.net/namespace/cpt#> .
@prefix ex: <http://mm2ttl.net/namespace/ex#> .

@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
```

Für `Kuhmilch` als OWL-Klasse verwenden wir den Namespace `:`. In ttl wird das Objekt `:Kuhmilch` also expandiert zu `http://mm2ttl.net/namespace/default#Kuhmilch`.

```
:Kuhmilch
   a owl:Class ;
   rdfs:subClassOf :Milch .
```

Für jede OWL-Klasse legen wir eine Test-Instanz an, im Beispiel `:Kuhmilch` das Objekt `ex:Kuhmilch_ID_1640204723`.

```
ex:Kuhmilch_ID_1640204723
   a :Kuhmilch .
```

Die von GenDifS angelegten Beispiel-Instanzen erhalten das Präfix `ex:`. ACHTUNG: Protege untedrückt in der Anzeige das Präfix. Alle Beispiel-Instanzen erhalten deshalb zusätzlich eine gut sichtbare ID, um eine Verwechslung mit den Klassen auszuschließen.



## A-Box Inferencing-Test

Um zu prüfen, ob die Übersetzung von GenDifS nach OWL korrekt erfolgt und in Kombination mit dem vorgesehenen Reasoner - hier dem OWL-RL-Reasoner [owlrl](https://pypi.org/project/owlrl/) - funktioniert, fügen wir den automatisch angelegten Beispiel-Instanzen zusätzliche Features hinzu. Beispiel:

```
ex:Milch_166726759
   a :Milch ;
   :hat_Herkunft ex:Kuh_166726759 ;
   ex:classifyLike ex:Kuhmilch_166726759 .

ex:Kuh_166726759
   a :Kuh .

ex:Kuhmilch_166726759
   a :Kuhmilch .
```

In diesem Fall ist `ex:Milch_166726759` eine Instanz der Klasse `:Milch`, aber nicht der Subklasse `:Kuhmilch`. Aufgrund ihrer Herkunft soll `ex:Milch_166726759` vom Reasoner jedoch gleich klassifiziert werden wie `ex:Kuhmilch_166726759`, also insbesondere als Instanz der Klasse `:Kuhmilch`.

Nach dem Inferencing durch `owlrl` sind für die Beispiel-Instanz `ex:Milch_166726759` u.a. die folgenden Tripel in der ausmaterialisierten ttl-Datei enthalten:

```
ex:Milch_166726759 a
        :Kuhmilch,
        :Milch,
        :topConcept,
        owl:Thing ;
    :hat_Herkunft ex:Kuh_166726759 ;
    ex:classifyLike ex:Kuhmilch_166726759 .
```

+++

## SKOS

Außerdem interpretieren wir die Mindmap als SKOS-Baum. Zur Klasse `:Kuhmilch` erzeugen wir ein Objekt `cpt:Kuhmilch` als Instanz der Klasse `skos:Concept`:

```
cpt:Kuhmilch
   a skos:Concept ;
   skos:broader cpt:Milch .
```

Die drei Objekte `:Milch`, `ex:Milch_166726759` und `cpt:Milch` haben also unterschiedliche IRIS und bezeichnen unterschiedliche Dinge. Sie können in der selben ttl-Datei nebeneinaner auftreten und in Beziehung treten, ohne dass man mit Punning etc. arbeiten muss.
