Letzte Woche angeschaut, wie wir Prädikate definieren können durch Aufzählung von Fakten,
eine exzensionale Definition eines Prädikats. Wir hatten uns angeguckt,
wie wir Anfragen an diese Faktensammlung stellen können.
Wir hatten das mit Grundthermen gemacht, also vollständig instanziierten Anfragen.
Wir hatten dann den vajablen Begriff eingeführt und der Punkt,
wo wir angekommen waren, Der Punkt, wo wir angekommen waren,
war, dass wir durch unterschiedliche Instanziierungsvarianten ein unterschiedliches Verhalten des Programms hervorrufen können.
Entweder wir rufen das Ganze vollinstanziert auf und kriegen nur eine Information,
ob dieses Tupel zur Relation dazugehörig ist oder nicht.
Oder wir rufen es partiell oder vollständig instanziert auf vollständig uninstanziert auf,
dann kriegen wir eine Aufzählung, all der Vagablenbindungen,
die benötigt werden, um Tupel aus der aus der Datenbank zu erzeugen.
Und dadurch, dass wir die Wertebindung natürlich wieder in die Anfrage einsetzen können,
kriegen wir also eine Aufzählung von Teilen der Relation oder von der gesamten Relation,
wenn wir das vollständig unnütz sanziiert aufrufen.
Eine kleine Nebenerkenntnis war, dass wenn immer wir eine gleiche Variable verwenden,
Co-Referenz zwischen den Variablen besteht und damit eine Bedingung formuliert wird,
auch wenn wir nichts über die Identität der Variablenwerte aussagen können.
Allein die Tatsache, dass wir fordern,
das hier muss gleich dem sein, führt dazu,
dass in dieser Datenbank mit den vier Fakten kein einziges Tupel
existiert,
was die Anfrage wahrmacht
Gut,
dann hatten wir das auf komplexe Teilziele erweitert und kriegen dann eben ein etwas aufwendigeres Suchproblem,
wo wir mit dem ersten Teilziel in die Suche gehen,
was immer, weil ihr als Vayablenbindung für dieses erste Teilziel bekommen,
wird dann als Instanziierung für das zweite Teilziel verwendet und mit dieser instanziierten Variante des zweiten Teilziels geht es dann wieder in die Suche nach einer Bestätigung.
Und da das jetzt hier vollständig instanziert ist,
geht es nur noch um die Frage,
stimmt es oder stimmt es nicht?
In diesem Fall stimmt es,
sodass diese variablen Bindung durch das zweite Teilziel bestätigt worden ist
und als Ergebnis nach außen ausgegeben werden kann
Das war der Punkt, bis zu dem wir gekommen waren.
Wir machen jetzt noch ein kleines Schmankerl, das ist die
sogenannte anonyme Variable. Im Gegensatz zu einer benannten Variablen,
die ja immer mit dem Großbuchstaben anfängt,
ist die anonyme Variable einfach nur ein Un- underscore.
Es hat eine etwas abweichende Semantik gegenüber der benannten Variablen,
denn hier wird keine Chor-Referenz hergestellt.
Wenn ich also in einer Anfrage mehrfach anonyme Variablen verwende,
dann ist das nicht die gleiche Variable,
sondern das sind unterschiedliche Variablen
Der einzige Verwendungszweck ist, um Programme übersichtlicher zu machen,
wann immer ich in einer Anfrage nicht alle Informationen benötige,
könnte ich auch immer Variablen dorthin schreiben, also benannt
Variablen, dahin schreiben, um deutlich zu machen, dass der Wert dieser Variablen irrelevant ist,
verwende ich die anonyme Variable. Also in dieser Anfrage hier,
wo ich nur wissen will, welche Mehrfamilienhäuser gibt es,
ich interessiere mich also nicht für das Baujahr,
ich interessiere mich auch nicht für den Identifier in der Datenbank,
ich will nur wissen, welche Adresse haben mehr Familienhäuser,
dann kann ich eben hier diese Argumentposition mit anonymen Variablen versehen und dann wird das auf der Oberfläche
Also wenn ich am System prompt bin, werden die vaiablen
Bindungen dafür eben nicht ausgegeben. Ansonsten würden hier vier Variablen
ausgegeben werden müssen und dann wird es etwas unübersichtlich.
In anderen Programmen zusammenhängen kann ich es natürlich auch verwenden.
Dann dient es aber eben nur dazu,
die Lesbarkeit des Programms zu verbessern.
Dass ich also dem Leser des Programmes von vornherein deutlich mache,
dieser Variablen Bindung ist für mein,
also diese Argumentposition ist für mein Verarbeitungsproblem irrelevant
Gut, wir erweitern jetzt die Datenbank nochmal ein bisschen,
indem wir jetzt auch noch Besitzwechselvorgänge mit hinzufügen,
die jetzt also sagen, es gibt einen Besitzwechselvorgang,
das ist also ein Identifier hier vorn wieder,
dann bezieht es sich auf eine bestimmte Immobilie,
also in diesem Fall die Immobilie Nummer eins und die
hat irgendwann mal den Besetzer von Müller zu Meyer gewechselt,
zu einem bestimmten Verkaufspreis und zu einem bestimmten Datum und für
das Datum habe ich hier einfach eine Repräsentation aus Jahr,
Monat und Tag genommen
Und ja, an solche eine Datenbank können wir jetzt
komplexe Anfragen stellen. Jetzt sind wir erstmalig so weit,
dass wir nicht nur ein Prädikat uns anschauen,
sondern zwei Prädikate und die natürlich,
da sie hier in der Definition nicht aufeinander bezogen sind,
wir werden dann auch noch den Fall kennenlernen,
dass wir mit einem Prädikat auf das andere zurückgreifen können.
Aber dazu brauchen wir den Deduktionsbegriff erstmal. Hier haben wir
zwei exzensional aufgezählte Relation. Und der Bezug zwischen den beiden
wird also nur durch Anfragen hergestellt. Und das ist genau das,
was ein Join in der Welt der relationalen Datenbanken ist.
Ich kann also jetzt beispielsweise fragen, wer hat welches Haus gekauft,
also eine Anfrage nach einem bestimmten Objekt.
Und jetzt ist er Adentifier für das Objekt
Interessant, denn nur über den Identifier kann ich den Bezug zum Besitzwechsel herstellen.
Hier ist die Chor-Referenz zwischen diesen beiden X Vorkommen und ich möchte haben
die Straße und die Hausnummer und ich möchte den Käufer wissen.
Also wer hat welches Haus gekauft? Ich kriege natürlich
auch hier noch mit den Wert der Joint-Vayablen ausgegeben,
also dass es sich um das Objekt Nummer 1 handelt.
Wenn ich den unterdrücken will, muss ich ein Frepper außenrum
rum schreiben, kriegen wir später. Wesentlich ist,
dass also das, was den Joint ausmacht,
die Chor-Referenz der Vayablen ist und was wir hier machen,
ist sozusagen nichts anderes als eine neue Relation über den betreffenden Domänen herzustellen.
Dass wir also auf der Basis dieser beiden ursprüngliche Relation
eine neue definieren, die jetzt besteht zwischen dem Objektidentifikator,
zwischen der Straßenangabe der Hausnummer und dem Käufer.
Also eine vierstellige Relation wird hier definiert. Die hat
noch keinen Namen. Dieser Relation einen Namen zu geben,
das wird der nächste Schritt in den deduktiven Datenbanken sein. Gut,
ich mache jetzt einen kleinen Exkurs in die Welt der Prädikate höherer Ordnung,
obwohl die Prädikate höherer Ordnung im logischen Gang der Vorlesung
erst viel,
viel später drankommen
Werde ich wenigstens eins hier behandeln, weil es sehr nützlich
ist und weil es die Basis für alle Aggregationsfunktionalität bereitstellt.
Also wann immer ich etwas zählen will, sammeln will,
Mittelwerte bilden will, maximal oder minimal bestimmen will,
dann ist der Rückgriff auf das Find All unverzichtbar.
Find All macht also nichts anderes, als dass es ein Ziel bekommt.
Und in diesem Ziel müssen Vayablen drin sein.
Und diese Vayablen kann ich hier in einen Therm einfügen,
Und dann werden alle instanziierten Varianten dieses Terms in einer Liste gesammelt.
Wir kriegen hier indirekt ein so ein taktisches Konstrukt mit,
was sich bisher noch nicht offiziell eingeführt habe, nämlich die Liste.
Auch die Listenverarbeitung kommt später, weil sie nämlich eigentlich nichts
als so ein taktischer Zucker ist, der das Programmieren bequem macht,
aber für das logische Grundprinzip der Logik-Promierung eigentlich gar nicht gebraucht wird.
Es ist eine rekursive Datenstruktur wie jede andere rekursive Datenstruktur auch,
aber weil sie so häufig gebraucht wird,
führen wir eine spezielle Syntax hierfür ein und die wird jetzt hier gleich auftauchen.
Das Ganze macht also nur dann Sinn,
wenn es zwischen diesem Ziel hier und diesem Term
irgendwelche gemeinsamen Variablen gibt und die sollten instanziert sein,
damit sie im Prozess des Suchens aller Bajablen wertet,
erst instanziiert werden können.
Es macht nur Sinn, dieses Find All in dieser Instanziierungsvariante aufzurufen,
also der Therm ist gegeben,
das Ziel ist gegeben und die Liste kommt als Ergebnis heraus.
Das Ganze ist ein Petikat zweiter Ordnung,
weil es ein Prädikatsaufruf als Argument wert nimmt.
Also hier an dieser Stelle erfolgt ja ein Aufruf eines anderen Prädikats.
Daher die Zuordnung zu den Prädikaten zweiter Ordnung
Hier ein paar Beispiele. Ich kann jetzt also in diesem Fall alle Objekte sammeln,
die Einfamilienhäuser sind und ich will deren Baujahr wissen. Das heißt,
in dieser Liste L werden jetzt alle Baujahre gesammelt,
denn B ist die einzige Variable, die zwischen dem Thermen hier,
das ist die einfachste Form eines Thermens,
nämlich nur bestehend aus einer Variablen und dem Argumentwert hier die Co-Referenz herstellt.
Das heißt, es ruft dieses Ziel auf,
schickt es in die Datenbanksuche und alle Instanzierungen für B
werden in der LSDL aufgesammelt
Man kann auch,
und da sieht man das hier an dieser Stelle,
komplexere Therme verwenden, hier also ein Zweistelliger,
der aus einem Prädikatsnamen besteht und, also einem Funkler,
genauer gesagt, das ist ja noch kein Prädikat,
einem Funktor und das Ganze ist zweistellig.
Und die Variablen werden jetzt hier gebunden durch den Aufruf in dieser Objektdatenbank,
sodass der Straße und die Nummer,
die Hausnummer durch den,
durch das Ziel hier instanziert werden und in diese Therme substituiert
werden und alle diese Therme werden in der Liste L gesammelt
Hier gibt es noch ein kleines Schmankerl,
dass das nicht nur die Anfrage an die Datenbank ist,
die ich hier losschicke, sondern dass ich noch eine zusätzliche Bedingung formuliere.
Das ist nämlich dieses B hier immer größer als 1960 sein muss.
Also heißt es nichts anderes, gib mir die Adressen
aller Häuser, die nach 1960 gebaut worden sind.
Und die werden in der Liste L gesammelt,
in Form solcher Therme, Adresse, Gärtnerstraße 15,
ist ein Haus, was diese Bedingung erfüllt.
Also die Kombination aus der Bedingung,
ich bin ein Einfamilienhaus und ich bin nach 1960 gebaut worden
oder eben Gärtnerstraße 17 gehört auch dazu
Gut, also wir sehen hier zweierlei, die Therme können komplex sein.
Und die Ziele, die wir hier aufschreiben, können auch komplex sein.
Die können beliebig kompliziert sein. Es empfiehlt sich allerdings
auch hier wieder, wenn das hinreichend kompliziert wird,
dass man ein Prädikat dafür definiert und dann nur den Prädikatsaufruf dort reinschreibt.
Wie immer in der Programmierung abstrahieren, dem Ganzen einen Namen
geben und dann das wieder recyceln an einer anderen Stelle.
Wie wir das machen, kriegen wir aber erst später.
Deshalb ist es hier also aufgelistet. Da muss man abwägen,
ob das noch überschaubar genug ist oder nicht.
Wir werden weitere Prädikate, zweite Ordnung kennenlernen,
insbesondere Set of und Backoff,
aber das passiert in
ungefähr sieben Wochen
Ja, der Vergleich zur Welt der relationalen Datenbanken,
wo SQL als Abfragesprache dominiert. Beide haben die Relation Algebra
als Verarbeitungsmodell. Wir haben in der Relation Algebra die Selektion.
Das sind also in unserem Falle Anfragen, die wir stellen können,
wo über die Anfrage Tupel ausgewählt werden als relevant für die Anfrage.
Wir haben die Projektion, dass wir bestimmte Teile aus einer Tabelle,
also Spalten aus einer Tabelle sehen,
wollen andere nicht sehen wollen.
Das ist bei uns
eine Anfrage mit anonymen Vagablen
Wir haben den Join, dann haben wir eine mehr Tabellenanfrage mit gemeinsamer Variable,
die den Chor-Referenz und damit den Join herstellt.
Und wir haben aggregierende Operationen, sowas wie Count Max,
dass es nicht tatsächlich Bestandteil der Redaktionen, Algibra,
aber natürlich können wir das in SQL machen und wir können es auch hier,
das sind also Prädikate, zweite Ordnung, die wir dann verwenden werden.
Das Schöne an der Sache, das haben wir bisher gesehen,
die relationalen Datenbankabfragesprachen und das ist der Grund,
weshalb sie in der Informatik dominieren und dass man erst heute wieder anfängt,
nachzudenken, ob es nicht an einigen Stellen sinnvoll sein kann, dass strenge Gerüst der relationalen Datenbanken
etwas aufzuweichen bestimmten Anwendungserfordernissen ist eben genau der Grund, dass sie referenziell transparent sind.
Und damit richtungsunabhängig sind und dadurch etwas erlauben,
was für die Datenbankwelt essentiell ist, nämlich Datenabstraktion.
Dass ich zum Zeitpunkt des Sammelns der Daten nicht angeben muss,
in welcher Weise ich die Daten später mal verwenden will.
Und genau diese Idee der Richtungsunabhängigkeit,
die wollen wir eben retten in die allgemeine Programmierung oder schauen,
wie weit wir das in der allgemeinen Programmierung aufrechterhalten können
Der relationale Datenbank-Kern von Prolog, das ist also genau das,
was wir bis jetzt kennengelernt haben und nichts anderes.
Das ist vollständig Äquivalent zur Recherchefunktionalität von SQL. SQL enthält natürlich
noch mehr, nämlich, dass sich Tabellen definieren kann.
Haben wir auch schon in der Übung gesehen mit Asshört,
kann ich genau das Gleiche tun,
dass ich Fakten zu einer Relation hinzufüge.
Dieser Datenbank-Kern ist eine echte Teilmenge von Prolog.
Wir müssen also nichts wieder beseitigen. Wir werden jetzt
nur zusätzliche Konstrukte hinzunehmen. Das Ganze ist nicht berechnungsuniversell wie
jede Abfragesprache für eine Datenbank.
Natürlich erlaubt
auch SQL Berechnungen anzustoßen
Aber ich rede hier vom Recherche, von der Abfrage, Funktionalität, nicht von der Berechnungsrela.
Und ich kann natürlich auf relationale Datenbanken, Spezialprogrammiersprachen draufsetzen.
Das ist damit nicht gemeint, sondern es ist wirklich die Recherche,
Funktionalität, die vom relationalen Modell herkommt.
Was Datenbanksysteme natürlich gegenüber dem Prolog oder der Logikprogrammierung im Allgemeinen erlauben,
ist, dass sie die persistente Haltung großer Datenbestände erlauben,
das ist in einem Prolog-System natürlich nicht gegeben,
in dem Augenblick, wo ich ausschalte,
ist der Inhalt der Datenbank weg, unterstützen den mehr Benutzerbetrieb,
wir haben hier nur eine Konsole,
über die
wir alles steuern
Unterstützen, Wartung und Aktualisierung der Daten, das haben wir hier überhaupt nicht.
Also hier gibt es keine Backup-Funktionalität oder so etwas.
Wir können natürlich Dateien schreiben und wieder lesen.
Wir können uns sowas bauen, aber vom System her selber
wird sich unterstützt. Und sichern auch die Integrität der Daten.
Also wenn wir unsere Datenbank auf Konsistenz prüfen wollen,
auf das Einhalten bestimmter Bedingungen, dann müssen wir das selber programmieren.
Da gibt es also keine Funktionalität in Form von Checkklauseln oder Assursions
, wie in der relationalen Datenbankwelt etwa. Gut,
das soll nur andeuten, wir reden über das gleiche Konzept,
aber wir haben natürlich unterschiedliche Interessen und Erinnerungserfordernisse und da haben
wir dann auch die entsprechenden Abweichungen im Design der Systeme.
So, wir machen jetzt in diesem Durchgang,
den ich angekündigt habe, vom Einfachen zum Komplizierten,
wir haben das einfachste Modell, die relationale Datenbank kennengelernt.
Jetzt machen wir den ersten Schritt, dass wir zur
deduktiven Datenbank übergehen. Wir müssen also eins,
ein eins ist Konzept hinzunehmen und das ist der Begriff der Deduktion
und da müssen wir uns als erstes angucken,
was Deduktion ist und werden uns als zweites angucken,
wie wir Deduktion oder wie wir die Grundlage für die Deduktion in unserem Prolog-System einspeisen können.
Das werden Regeln sein
Und wir schauen uns dann an,
was wir mit diesen Regeln alles machen können,
nämlich deduktive Datenbanken aufbauen, für ganz bestimmte Relationstypen.
Die gucken wir uns dann im Weiteren an.
Die kennen sie alle schon, aus der Mathematik.
Das ist sowas wie Symmetrie, Transitivität und dergleichen mehr.
Und wir schauen uns dann immer an,
wie diese Eigenschaften sich in einem Polog-Programm widerspiegeln.
Und wir schauen uns auch an, welche Gefahren
damit möglicherweise verbunden sind. Wo wir hingucken müssen,
damit wir tatsächlich
sichere Programme schreiben
Und wir schauen uns dann eine Anwendung an,
wo wir die Fähigkeiten der deduktiven Datenbanken natürlich erstmal nutzen.
Und das wird ein Weg, Sucheproblem seien,
denn Wegplanung ist der prototypische Anwendungsfall für die Deduktion.
Wo ich eben in der Lage bin, lokale Verbindungen hinzuschreiben,
aber ich bin nicht in der Lage, alle Verbindungen,
die es zwischen zwei Punkten gibt, aufzuzählen.
Erstens ist die Menge unendlich groß und zweitens,
selbst wenn ich sie künstlich endlich mache,
ist sie immer noch so groß,
dass das nicht praktikabel ist
Also, was ist der Deduktion? Deduktion heißt nichts anderes,
als ich habe eine Aktionenmenge gegeben. Ich habe einen Folgerungoperator,
wie ich aus dieser Aktionenmenge Schlüsse ziehen kann. Und dieser Ableitungsprozess, das ist Deduktion. Also,
im einfachsten Fall haben wir Aussagen, Logik,
dann sind die Aktionen eben atomare Formeln und Implikationen und wir haben eine Schlussregel,
die ist der Modus Ponens, gibt auch andere,
aber nehmen wir einfach den, der also sagt,
wenn A gilt und es gilt, dass aus A,
B folgt,
dann kann ich damit ableiten, es gilt auch B.
Das ist Deduktion. Ich habe Fakten gegeben. Es gilt A,
ich habe Regeln gegeben, das wird unsere Redeweise in der Logikprogrammierung dann sein.
Und mit diesen Fakten und diesen Regeln kann ich neue Fakten ableiten.
Das ist der Begriff der Deduktion. Nimm Fakten,
Wende, Regeln darauf an und du bekommst neue Fakten heraus.
Das heißt also, ich bin jetzt in der Lage,
Relationen zu berechnen und nicht mehr nur noch aufzuzählen.
Das ist der entscheidende Schritt, den wir jetzt machen.
In der Prädikatenlogik ist es ein bisschen komplizierter und wir verwenden hier Prädikatenlogik,
weil wir natürlich Variablen haben wollen, sonst können wir nichts berechnen,
sonst kriegen wir immer nur Ja oder Nein raus.
Also so etwas wie Hans ist ein Mann, alle Männer sind Verbrecher,
daraus folgt, Hans ist ein Verbrecher, wäre in Prekaten,
Kalkül erster Stufe darzustellen, als Hans ist ein Mann,
ein einstelliges Prädikat.
Und eine Regel für alle X gilt,
dass aus Mann von X folgt Verbrecher von X. Und über
diesem Fakt und der Anwendung dieser allgemeinen Regel kann ich dann eben neue Fakten ableiten,
dass eben auch Hans ein Verbrecher sein muss.
Wir haben hier schon,
das Beispiel ist nicht ohne Grund gewählt, immer zu bedenken,
dass eine solche Regel ein sehr allgemeinen,
völlig unbeschränkten Zusammenhang über die Welt generiert
Was der Al-Quanto hier vorhin schon sagt, universell gültig.
Ausnahmen sind in dieser Regel nicht vorgesehen,
wie wir mit Ausnahmen umgehen können, das ist auch etwas,
was wir in einem späteren Kapitel uns angucken.
Wir arbeiten im Augenblick mit wirklich universell quantifizierten Regeln dieser Art.
Wenn wir also bisher eine Relation immer durch Aufzählen der Elemente der Fakten nämlich spezifiziert haben,
und das habe ich extensionale Spezifikation genannt,
dann sah also eine Relation so aus, dass sie definiert ist,
als Menge von Tupin.
Wenn das also jetzt hier eine M-stellige Relation ist,
dann sind das immer M-Tupel und die
sind durchnummeriert von 1 bis
Das ist eine exzensionale Spezifikation und das ist die Welt der relationalen Datenbanken.
Jetzt machen wir deduktive Datenbanken, jetzt geht es darum,
dass die Relation zu berechnen und zwar aufgrund von Regeln
und das nennen wir dann eine intentionale Spezifikation.
In der mathematischen Notation hieße das dann, wir reden über eine Relation,
die besteht aus einer Menge von Tupeln und alle diese Tupeln müssen bestimmte Bedingungen erfüllen.
Und ich kann, indem ich die Bedingungen anwende,
diese Tupel generieren, aber ich kann sie nicht,
ich muss sie nicht aufzählen, das ist das Wesentliche dabei.
Und die Regeln, die wir dafür brauchen,
also diese Bedingungen hier sind dann Implikationen in der Prädikatenlogik
Deduktion in diesem Sinne, das hatte ich schon gesagt,
ist dann eben die Ableitung neuer Fakten durch Anwendung der Regeln,
auf die bereits bekannten Fakten.
Wir im Analogie zur funktionalen Abstraktion, wo es darum geht,
Berechnungsprozesse in eine allgemeine Funktion zu abstrahieren,
dass sie also keine Tabellen aufschreiben muss.
Eins hoch 2 ist 1, 2 hoch 2 ist 4,
3 hoch 2 ist 9 und so weiter,
kann ich eine Funktion definieren,
bilde mir
das Quadrat einer Zahl
Genau in dem gleichen Sinne kann ich hier jetzt
generelle Vorschriften spezifizieren, die mir ganze Relationen aufzählen.
Und ich nenne das dann deshalb auch relationale Abstraktionen.
Relationale Abstraktion heißt also, baue solche intentionalen Spezifikationen,
wo Relationen berechnet werden, anstatt sie aufzuzählen. Und das dient eben,
wie üblich in der Informatik, um Redundanz zu beseitigen,
um das nicht alles aufzählen zu müssen und ist Voraussetzung dafür,
wenn ich über unendliche Domänen reden will, gilt es nicht anders,
als zu rechnen, anstatt aufzuzählen.
Also wir werden als Beispiel schon sehen,
wenn wir wirklich über natürliche Zahlen, nicht über Integer zahlen,
wenn wir über natürliche Zahlen reden wollen,
reden wir über
unendlich viele Elemente
Und die Frage ist, wie können wir damit umgehen?
Ja, was wir brauchen ist, wir müssen den Klauselbegriff etwas erweitern.
Wir hatten bisher Fakten, wir hatten Ziele,
wir brauchen jetzt noch die Regel und die Regel besteht immer
aus zwei Teilen einem Kopf der Regel und einem Körper der Regel.
Und dazwischen gibt es einen Separator, das ist der Doppelpunkt
minus, die Kombination aus Doppelpunkt und Minus.
Und das soll ein Verballhornter Pfeil sein, der von rechts nach links zeigt.
Wenn wir also vorher in der des Polens im Prädikatenkalkül hier
ein Implikationsfeil hatten, dann ist das genau dieser Implikationsfeil.
Nur wie üblich in der Informatik schreiben wir den andersherum,
soll heißen, wir definieren ein Prädikat mit diesem Namen hier
und wir definieren es um all das, was in dem Körper steht.
Und logisch gesehen heißt das nichts anderes,
als wenn immer der Körper wahr ist, dann folgt daraus,
dass der Kopf auch wahr ist.
Also die Sicht der Informatik ist ja genau umgekehrt,
als die Sicht der Logik, die sich der Logik sagt,
aus A folgt B und die Sicht der Informatik ist,
ich definiere B,
indem ich auf A zurückgreife
Das ist, warum man dort nicht einfach die Pfeile stimmen muss,
sozusagen mit dem Regal erreicht. Nö, das hat,
das ist Edinburgh Syntax, sie hat Dave Warren mal erfunden,
40 Jahre vorher und die ist seitdem unverändert geblieben.
Da hat nie irgendjemand den Versuch gemacht, das zu ändern.
Ich sehe auch keinen Grund, dass man das ändert. So,
dann müssen wir uns natürlich fragen,
was ist ein Kopf, was ist ein Körper,
haben wir alles schon gesehen,
der Kopf ist eine Struktur,
eine Struktur war immer etwas,
was aus einem Funktor besteht und in Klammern aufgelisteten Argumenten und der Körper ist ein Ziel und zwar ein beliebiges Ziel,
das heißt,
es kann ein komplexes Ziel sein,
es muss
kein elementares Ziel sein
Und die Beispiele, wir haben dann eben unsere Regel,
die wir vorhin hatten, Verbrecher. X ist ein Verbrecher,
wird definiert zu X ist ein Mann. Oder andersherum,
wenn X ein Mann ist, dann ist er auch ein Verbrecher.
Das ist eben genau dieser nach links gerichtete Implikationsfall.
Und wir können jetzt hingehen und Mann definieren, indem wir sagen,
ein Mann ist dadurch definiert, dass es ein Mensch ist,
er muss männlich sein und er muss erwachsen sein.
Und dann haben wir eben im Körper dieser Klausel ein komplexes Ziel aufgeschrieben.
Und ein Prädikat ist jetzt eine Menge von Klauseln mit gleicher Signatur.
Das heißt, wir können jetzt sowohl Männer aufzählen. Ja,
wir können sagen, Hans ist ein Mann und was weiß ich,
wer alles ein Mann ist. Wir können aber genauso gut
auch in dem gleichen Prädikat Regeln angeben und Männer berechnen.
Also wir können in einer Prädikatsdefinition Fakten und Regeln munter mischen.
Und das ist auch einer der Gründe,
weshalb der Unterschied zwischen Programmen und Daten in Produkt letztendlich völlig verschwindet.
Wir müssen uns über die Semantik einer Regel Rechenschaft ablegen.
Denortationell, es ist ganz einfach,
wir borgen wieder alles bei der Mathematik und sagen,
denotationell ist eine Regel das,
wo ich die logische Ableitung mit dem Modesponens
drüber laufen lassen kann
Und operational müssen wir das jetzt auf unsere virtuelle Maschine umsetzen.
Also wie arbeiten wir eine Regel tatsächlich ab? Wir unifizieren immer
den Regelkopf mit der Anfrage. Und falls das erfolgreich ist,
dann benennen wir alle Vayablen in der Klausel um, um Namenskonflikte zu vermeiden.
Das ist genau der Grund, weshalb sie im Trace,
wenn sie den einschalten, immer sowas wie G-175 sehen.
Das ist der Namens-Umbenennungsprozess, der immer automatisch abläuft,
den wir überhaupt nicht unterbinden können. Und der ist Voraussetzung dafür,
um den Skopus der Vayablen sicherzustellen, Eine Variable in der nächsten Klausel,
eine neue Variable ist und nicht die Alte.
Deshalb muss sie umbenannt werden. Auch wenn in allen Klauseln
X drinsteht, es sind tatsächlich unterschiedliche Variablen.
Also wir haben das hier gerade eben gesehen,
dieses X hier ist ein ganz anderes X als das.
Dieses X hier ist genau das gleiche X wie hier,
wie hier, wie hier, innerhalb der Klausel, gilt Identität.
Über die Klauselgrenzen hinweg sind das unterschiedliche Variablen.
Dann nehmen wir die den Regelkörper und ersetzen die Anfrage,
was ja unser ursprüngliches Ziel gewesen ist,
ersetzen wir durch das, was im Regelkörper steht.
Und wir verwenden da bei all die vaiablen Bindungen,
die bei der Unifikation, das ist nämlich hier oben,
der Schritt, bei der Unifikation des Regelkopfes erzeugt worden sind.
Die vaiablen Bindungen werden genommen und in den Regelkörper substituiert.
Und dann wird der Regelkörper genommen und als neue komplexe Anfrage in die Verarbeitung geschickt.
Jetzt kriegen wir also sozusagen eine Rekussion hinein, die sagt,
ich habe ein Ziel und ich möchte dieses Ziel mit Hilfe einer Regel abarbeiten.
Und dadurch generiert mir die Regel neue Ziele,
indem sie nämlich genau den Regelkörper an die Stelle des alten Regelziels setzt.
Und diese Ziele im Regelkörper können natürlich wieder neue Ziele generieren,
weil sie auf neue Regeln zurückgreifen. Das heißt also,
Regeln führen jetzt dazu, dass sich unser Suchraum weiter aufspalten wird.
Also wir werden weitere Suchschritte in unserem Suchraum hinzubekommen,
weil wir jetzt immer gucken müssen,
ein Fakt hat sozusagen immer die Ableitung abgeschlossen bisher.
Da war ein Blattknoten erreicht. Wenn wir jetzt eine Regel anwenden,
wird eine neue Verzweigung im Suchraum generiert,
weil wir jetzt nämlich die neuen Alternativen eines neuen Teilzieles
dort abarbeiten müssen
Gut, zur Pragmatik können wir auch ein bisschen was sagen.
Normalerweise wird ein Regelkopf keine Grundstruktur sein. Das macht keinen Sinn
. Wir wollen Berechnungsergebnisse haben und dafür brauchen wir Vayablen.
Und die Vayablen des Regelkopfes sind eigentlich nichts viel anderes.
Sie sind tatsächlich etwas anderes als die formalen Parameter einer Prozedur.
Sie sind die formalen Parameter einer Prozedur unter den Bedingungen
der Richtungsunabhängigkeit, die in den anderen Programmiersprachen nicht gilt.
Da lässt Prologs zu, dass man bei der Formulierung von Pegel
, das ist eine Rekrusion einbaut.
Ja, unbedingt, ja, ja.
Ja, unbedingt.
Das wird eines
Das ist das, womit wir uns in den nächsten Wochen auseinandersetzen müssen, ja.
Das ist die Hauptfrage, die wir uns umtreiben wird.
Wie können wir verhindern, dass in diesem Falle das Ganze
nicht mehr terminiert? Wir gucken uns jetzt, nein,
wir gucken uns auch heute schon die ersten Beispiele dafür an. So,
hier noch nicht, doch hier auch,
aber hier ist es noch nicht dramatisch, weil hinreichend instanziert,
wir erwähnten unsere vier Faktdatenbasis, wer oder was liebt,
wer liebt irgendwas oder wen, erweitern wir durch eine solche Regel,
die also sagt,
Paul liebt alle diejenigen,
die Bücher mögen
Eine Generalisierung über das, was Paul wohl so üblicherweise an Freunden hat.
Wenn wir das jetzt machen, müssen wir uns als erstes
überlegen, was hat das Konsequenzen für unser Testregime?
Also kriegen wir neue Testfälle hinzu, die wir beim Testen berücksichtigen müssen.
Und das ist tatsächlich so. Wir hatten also bisher,
wir müssen immer positive und negative Beispiele angucken. Wir hatten die Forderung,
wir müssen uns alle Instanziziierungsvarianten angucken und wir müssen uns jetzt auch noch,
das ist wie überall in der Programmierung, alle wesentlichen Fallunterscheidungen angucken.
Ja, das ist ja das Übliche wie ein Testgenerator herangeht,
dass er die ganzen IF-Klauseln, also sorry,
die IF-Ausdrücke aus einer Programmiersprache hernimmt und daraus dann die relevanten Testfälle generiert und das Gesir nicht anders.
Wenn wir also eine solche Datenbank haben, dann haben wir die große Unterscheidung,
wir können einerseits über die Fakteninformationen ableiten und wir können andererseits über die Regel die Informationen ableiten.
Beide Fälle sollten hinreichend repräsentiert sein in den Testfällen. So,
wir fangen also wieder vollständig instanziiert an,
liebt Paul Karl und wir haben hier im Wesentlichen die Testfälle,
die wir bisher noch nicht gesehen haben, die,
die ohnehin mit den Fakten beantwortbar sind,
die sind nicht mehr so relevant.
Da haben wir schon gesehen, wie sich das Programm verhält.
Wir haben jetzt mit bewusst irgendetwas hinzugenommen,
wo die Regel relevant ist und die sagt nun mal
etwas über Paul aus und über nichts anderes
Wir gehen mit dieser Frage wieder in die Datenbank,
die vier Fakten, sagen allesamt nichts über Paul aus.
Das heißt, da gibt es kein Ergebnis. Wir haben
aber jetzt eine fünfte Alternative und das ist diese Regel.
Wir unifizieren die Anfrage mit dem Regelkopf und kriegen dadurch die
Instanzierung für X1. X1 wird auf dem Wert K gesetzt.
Und mit dieser variablen Bindung nehmen wir den Körper der Klausel
und aktivieren ihn als neues Teilziel in der Suche.
Das heißt, X1 hat jetzt den Wert K,
das heißt, das neue, das neue Teilziel ist jetzt,
liebt, was war das,
Karl,
ein Buch
Und mit dieser Anfrage geht es wieder rein in die Datenbank,
die ist jetzt vollständig instanziert.
Und mit dem vierten Fakt kriegen wir die Bestätigung dafür,
das heißt, diese vaiablen Bindung X1 gleich K ist offensichtlich
eine gute vaiablen Bindung gewesen.
Also Paul Markal, weil Karl eben Bücher nach ist.
Und wir haben wieder das alte Verhalten sein,
was wir ja schon bei den relationalen Datenbanken gesehen haben.
Wenn wir vollständig instanziert aufrufen, dann ist es der Test
auf Enthaltensein des Elementes in der Relation.
Denn wir kriegen nach außen hin
keine vaiablen Bindung mitgeteilt
Das sollte deutlich werden. Wir rufen, das vollständig instanziert
auf. Da ist keine Variable drin. Das heißt,
das Prologsystem teilt uns auch nicht mit, was es intern gemacht hat.
Dass es hier intern eine für diese lokale Variable X1,
eine Bindung hergestellt hat, um nämlich die Choreferenz zwischen dem
Kopf der Klausel und dem Körper der Klausel herzustellen.
Davon erfahren wir gar nichts. Wir erfahren nur das Ergebnis True,
weil dieser Aufruf hier erfolgreich war, der bestätigt diese Variable
Mindung X1 gleich K. Und die bestätigt,
dass dieser Aufruf ursprünglich mal zur Relation dazugehört
Das Gleiche nochmal im Trace. Wir gehen mit der Anfrage
, liebt Paul Karl in das Rennen.
Wir haben die ersten vier Fakten, die nichts über Paul aussagen.
Das heißt, die Unifikation scheitert immer auf der ersten Argumentstelle.
Wir kommen zu der Regel, da ist die Unifikation mit dem Regelkopf erfolgreich.
Funktor ist identisch, Stelligkeit ist identisch. Auf der ersten
Argumentstelle unifiziert ist, auf der zweiten Argumentstelle unifiziert ist auch,
in dem X1 auf Karl gebunden wird.
Das steht hier hinten als Valiablen benunkt da.
Und wir nehmen diese Valiablenbindung substituieren X1 im Körper der Klausel
mit dem Wert Karl und kriegen den Aufruf,
liebt Karl ein Buch als neuen Aufruf für die Suche.
Und das heißt, wir machen einen neuen Entscheidungspunkt auf
Und dann wird mit der neuen Anfrage der Körper abgearbeitet. Ich sehe gerade,
ich vermute mal, das ist noch die alte Version der Abarbeitung,
wo nach dem ersten erfolgreichen Bestätigung die Suche abbricht,
vermutlich vermutlich erlaubt es uns,
das System in der jetzigen Variante hier nochmal eine Frage nach Alternativergebnissen zu stellen.
Und dann müssten wir ein zweites Droh bekommen,
denn es gibt ja auch noch nicht nur Karl in Einhalt, Variable.
Ist richtig, ja, aber das ist eben früher,
wenn keine Variable drin war, dann kam nur True oder False raus.
Bei der jetzigen Version ist es tatsächlich so, so oft,
wie er das Ding wahrmachen kann, sagt er True.
Und bietet einem immer an, es gibt noch weitere Ergebnisse.
Und ich vermute mal, dass dieser Fall hier,
es ist immer schwierig zu beantworten, die Frage, weil bei der Anfragebearbeitung Optimierungsschritte gemacht werden.
Aber in diesem Fall muss er es machen, denn es gibt neben Nein,
es war Paul Karl, es gibt nur einen,
sorry, es gibt nur ein Ergebnis und dann,
das müsste ich jetzt ausprobieren, ob er hier schon erkennen kann,
dass es ein weiteres Ergebnis gar nicht geben kann.
Wenn wir nämlich den Suchraum abarbeiten müssten, ja,
dann würden wir feststellen, na gut, den Schritt machen wir gleich,
wenn wir Vajablen verwenden, das kann man da viel besser sehen.
Das ist ein partiell instanziertes Ziel,
jetzt lassen wir nämlich hier den Karl weg und schreiben dort eine Vajable hin,
also wen oder was wie Paul und wir kriegen,
wie bisher auch schon mit den Fakten kein Ergebnis,
wir müssen die Regel bemühen,
die Regel instanziert jetzt diese Vagable durch eine Co-Referenz mit der nach außen sichtbaren Vayablen X. Das heißt,
wir haben jetzt die Co-Referenz,
der war wert der Vayablen X, wird das sein,
was immer hier bei der weiteren Berechnung für X1 instanziert wird.
Ja, hier wird also jetzt bereits eine Cho-Referenz aufgebaut mit
dieser Vayablen Bindung geht es in den Körper der Klausel,
im Körper der Klausel wird jetzt also dieses partiell instanziierte Teilziel bearbeitet.
Das scheitert auf den ersten beiden Argumenten,
weil wir hier hinten Bücher verlangen und mit dem ersten Fakt,
der über Bücher spricht, das ist nämlich Susi, die Bücher mag,
wird X1 an Ess gebunden und da X1 gleich X ist,
wird X, der Wert von X, nämlich Susi,
nach draußen ausgegeben.
Das ist das erste Ergebnis,
was wir sehen
Dann, wenn wir jetzt nach Alternativen fragen,
dann wird die zweite, wird der nächste Fakt angefasst.
Jetzt wird X1 auf Karl instanziert. Ja, also das ist X1
war ja die erste Argumentstelle, wird mit Karl instanziert.
Und wir kriegen wegen der Korreferenz mit X
als zweiten Wert für X Karl ausgegeben.
Und wenn wir jetzt wieder nach Alternativen fragen,
dann kommen wir wieder zu der Regelabarbeitung.
Wir müssen also den Regelkopf mit der Anfrage unifizieren.
Das führt zu den bayablen Bindungen X1,
ist gleich
P. Und X2 ist gleich
Moment. Genau. Und jetzt müssen wir diese Wertebindung für
X2 im Körper der Klausel zur Anwendung bringen.
Da müssen wir hier substituieren. Das heißt, die neue
Anfrage wird sein, lieben Bücher, Bücher. Ja,
das ist die neue Anfrage, mit der es ins Rennen
geht und weder die Fakten noch die Regeln passen auf diese Anfrage.
Das heißt, weitere Ergebnisse kriegen wir durch diesen Aufruf nicht.
Damit ist dieser Entscheidungspunkt vollständig abgearbeitet,
da auch hier bereits die letzte Klausel bemüht worden ist,
ist dieser Entscheidungspunkt vollständig abgearbeitet.
Und auch hier waren wir bereits bei der letzten Klausel angekommen,
das heißt auch der oberste Entscheidungspunkt ist vollständig abgearbeitet,
weitere Ergebnisse gibt es nicht
Das Gleiche wieder in der komplementären Sicht im Trace.
Wir gehen mit dem mit dem partiell instanzierten Ziel.
Paul X liebt Paul X in das Rennen. Wir machen
einen Entscheidungspunkt auf. Wir gucken uns die Fakten an.
Keiner davon unifiziert mit diesem Paul auf der ersten Argumentstelle.
Aber die Regel ist einschlägig. Da gelingt die Unifikation.
X wird an X1 gebunden. Diese Choreferenz wird hergestellt.
Wir gehen mit dieser vaiablen Subsituation in den Körper der Klausel
und machen dort einen neuen Entscheidungspunkt auf
Wir müssen wieder als erstes die Fakten anschauen. Der erste unifiziert nicht mit,
weil auf der zweiten Argumentstelle kein Buch angesprochen wird.
Das zweite Fakt, genauso der dritte Fakt,
unifiziert und bindet X1 an Susi und da X gleich X1,
jetzt gleich Susi gilt, wird das als erstes Ergebnis ausgegeben.
Die Frage nach der Alternative sagt,
gehe zu dem aktuellen Entscheidungspunkt zurück und mache die Vajablenwendung rückgängig.
Wir machen Backtracking und prüfe weitere Alternativen. Die drei Fakten haben wir bereits angefasst,
also kommen wir zu dem vierten Fakt in der Liste und instanzieren
jetzt X1 mit Karl, kriegen als neue Wertebindung für X,
Karl heraus und können wieder nach Alternativen fragen
Die, da wir jetzt alle vier Fakten bereits abgearbeitet haben,
in diesem Entscheidungspunkt zwei, bleibt uns nur noch die Regel übrig.
Die Regel führt dazu, dass X2, im Moment X1
an Paul gebunden wird und X2 an Buch gebunden wird.
Das steht hier hinten. Und mit dieser Wertebindung geht es in den Körper der Klausel,
da wird X2 durch Buch ersetzt und gibt die neue Anfrage,
lebt Buch, Komma, Buch.
Das macht einen neuen Entscheidungspunkt auf, wir gehen die Fakten durch,
die passen alle nicht, wir gucken die Regel an,
da passt der der Regel nicht.
Das heißt, dieser Entscheidungspunkt 3 ist vollständig abgearbeitet.
Wir machen Backtracking zum Entscheidungspunkt 2. Das Backtracking liefert kein
neues Ergebnis, weil wir bereits alle abgearbeitet haben.
Damit ist der Entscheidungspunkt 2 fallständig abgearbeitet. Wir müssen Backtracking
zum Entscheidungspunkt 1 machen. Auch dort haben wir keine Alternativen mehr
zur Wahl. Alle fünf sind bereits abgearbeitet. Das heißt,
es kommt ein Falls raus, so viel wie weitere Ergebnisse
sind nicht auffindbar
So, das war zweite Argumentstelle, ist unterspezifiziert.
Jetzt gucken wir uns das Gleiche auf der ersten Argumentstelle an.
Ich werde jetzt langsam anfangen, immer weniger Informationen hier zu präsentieren.
Also das Ziel ist, den Blick hinter die Kulissen
immer weiter zurückzunehmen und sich nur noch aufgrund der deklarativen Semantik
auf der Oberfläche zu überlegen, was passiert dort eigentlich.
Ich lasse als erstes mal den Baum weg. Hier ist
nur noch der Trace. Wir haben die erste Argumentstelle unterspezifiziert,
die zweite fordert Buch,
das unifiziert mit dem dritten Fakt und liefert das erwartete Ergebnis,
dass X Susi Also Susi mag Bücher, ein Ergebnis ist,
das Backtracking ruft den vierten Fakt auf und der ist auch erfolgreich,
der liefert die zweite Variablenbindung Karl für X.
Und danach werden wir wieder nach alternativen Fragen,
kommen wir zu der Regel,
die Regel liefert jetzt die bayablen Bindung X,
ist gleich Paul und X1 ist gleich Buch und das sollte uns verdammt bekannt vorkommen.
Wenn wir nämlich jetzt diese Variablenbindung nehmen und hier im Körper der Klausel substituieren,
kriegen wir wieder diese merkwürdige Frage heraus, lieben Bücher, Bücher.
Und wenn wir mit der in die Suche gehen,
das hatten wir bereits auf der vorhergehenden Folie,
gibt es keine weiteren Ergebnisse.
Wir müssen Backtracking zum Entscheidungspunkt 1 machen
Im Entscheidungspunkt eins waren wir bei der letzten Klausel schon angekommen.
Weitere Alternativen gibt es nicht. Das heißt, insgesamt kommt ein Fouls heraus.
Und hier und auf der vorhergehenden Folie haben wir eben gesehen,
wir kriegen hier wieder, wie im Falle der relationalen Datenbanken,
wenn wir mit einer partiell,
mit einem partiell instanzierten Ziel in die Suche einsteigen,
kriegen wir die Aufzählung aller Elemente der Relation,
die der Anfragebedingungen genügen.
Nämlich genau liebt Susi-Buch und liebt Karlbuch.
Das sind die beiden Ergebnisse hier auf der Folie davor,
waren es eben zufälligerweise auch zwei und zwar genau die gleichen Variablenbindungen.
Nur da war es eben auf der zweiten Argumentstelle
Aber das ist reiner Zufall, dass es auch da zwei gewesen sind.
Wir können das vollständig uninstanziert aufrufen. Also wer liebt was?
Und dann kriegen wir eben mit dem ersten Fakt das erste Ergebnis mit dem zweiten Fakt,
das zweite Ergebnis mit dem dritten Fakt,
das dritte Ergebnis, mit dem vierten Fakt,
das vierte Ergebnis, dann kommen wir zu der Regel,
da wird X an Paul gebunden und Y an X1,
also nur diese Co-Referenz hergestellt.
Und mit dieser bayerablen Bindung geht es in den Körper
der Klausel, der sagt, wer liebt Bücher?
Und die Frage sollte uns schon wieder bekannt vorkommen.
Die haben wir nämlich vorhin gerade gestellt
Damit kriegen wir zwei weitere Ergebnisse, nämlich Susi-Lieb-Bücher,
Carlib-Bücher, sodass wir insgesamt auf sechs Ergebnisse kommen.
Also Hans liebt Geld, Hans liebt Susi, Susilib-Bücher, Carlib-Bücher.
Paul liebt Susi und liebt Karl. Das sind dann die Ergebnisse,
die wir herausbekommen. Und im Dress das Ganze nochmal,
die Fakten liefern also die ersten Tupel aufgrund der Faktenlage eben die Anwendung der Regel,
führt auf die Anfrage, wer liebt Bücher?
Dafür kriegen wir die vayablen Bindung Susi und Karl und zusammen mit der Information,
die wir schon beim Identifizieren des Kopfes hergestellt haben,
dass X nämlich gleich Paul ist,
kriegen wir das vierte Das fünfte Ergebnis und mit diesem Karl zusammen das sechste Ergebnis.
Und wir haben damit dann eine vollständige Aufzählung der Relation wieder,
so wie wir das auch in der relationalen Datenbankwelt hatten.
So, wir haben, es sieht unscheinbar aus,
aber wir haben damit einen ziemlich mächtiges Werkzeug eingeführt in das Programmiersystem.
Die erste Konsequenz ist, unsere Suchräume werden sichtlich unübersichtlicher.
Sie können sich leicht den Tag ausmalen,
wo wir nicht mehr in der Lage sein werden,
den Suchraum tatsächlich noch vollständig abzuarbeiten. Das ist der Punkt,
wo auch der vollständige Dress im Produc-System uns nicht weiterhilft,
dann kann man noch versuchen über über lokale Traces,
dass man bis zu einem bestimmten Punkt laufen lässt und dann den Drehs einschaltet und so weiter,
die Sache zu regeln.
Aber auch das wird zunehmend unübersichtlich. Deshalb ist es also
wichtig über die Programme auf abstrakter Ebene nachzudenken.
Was machen wir dort eigentlich? Welche Art von Relation wollen wir
spezifizieren und welche Pattern gibt es, um bestimmte Relationen realisieren zu können?
Und das gucken wir uns im Weiteren jetzt an.
Also wir fangen einfach an. Symmetrie,
das ist ein Begriff, der im Alltag ja weitgehend geläufig ist,
was symmetrisch ist, immer irgendetwas, was spiegelbildlich ist,
was wir austauschen können.
Also wir reden nicht über Punktsymmetrie,
wir reden über den klassischen Fall der Spiegelung an einer Garaden
Und mathematisch heißt das also,
wenn das Paar XY in einer Relation P steht,
dann steht auch das Paar Y X in dieser Relation.
Das muss allgemeingültig sein. Das muss für alle Elemente der Relation gelten,
dann ist sie symmetrisch. Wir können uns Beispiele angucken,
klassische Symmetrie, symmetrische Relation ist, ist Zwillingsrelation.
Wenn ich Zwillingsgeschwister von einer anderen Person bin,
dann gilt das auch in der anderen Richtung.
Und wenn wir das in unserem Prolog-System realisieren wollen,
bleibt uns nichts anderes übrig, als die Sachen aufzuzählen oder zu berechnen.
Wenn wir sie aufzählen, müssen wir also immer dafür sorgen,
dass wir das in der Einrichtung angeben, aber in der anderen Richtung auch.
Also hier ist das Beispiel, wir machen es erstmal nur in eine Richtung,
Paul und Anne sind Zwillingsgeschwister und Hans- und Dienersitz, Willingsgeschwister.
Und wenn wir jetzt fragen, sind Paul und Anne Zwillingsgeschwister,
dann kommt Truh raus, na das haben wir erwartet.
Aber wenn wir es umdrehen, kommt natürlich Falls heraus.
Denn über Anne und Paul weiß diese Relation nichts.
Das ist nicht das gewünschte Ergebnis. Das ist nicht symmetrisch.
Wir wollen es aber symmetrisch haben. Wir merken uns nur,
wenn wir etwas extensional spezifizieren, also durch Aufzählen,
dann ist die zweistellige Relation standardmäßig unsymmetrisch.
Wenn wir sie symmetrisch haben wollen,
müssen wir aktiv
was tun dafür
Und die beiden Möglichkeiten, die wir haben, nein,
eigentlich drei, es gibt noch eine dritte, es gibt drei Möglichkeiten.
Entweder wir führen Redundanz in die Datenbank ein,
indem wir also immer das doppeln, wenn Paul und Anne drinsteht,
dann muss auch Anne und Paul drinstehen.
Und wenn Hans und Ina drinstehen,
dann müssen auch Hans und Nieder, Nina und Hans drinstehen.
Das ist eben Redundanz, weil das Information ist,
die man eigentlich berechnen könnte. Es ist zu beachten,
dass diese Redundanz auch aus einer relationalen Datenbank nicht wegzukriegen ist.
Das ist genau die Welt der relationalen Datenbanken. Die ist,
die kriege ich dort nicht heraus, die bleibt drin.
Das ist also die unattraktive Variante,
Wir können ein Hilfsprädikat definieren, in dem wir sagen,
ja, Zwilling von XY greift auf eine Faktensammlung,
die hier ZV genannt ist.
Wir hatten nur eine Abkürzung für Zwilling von,
zurück und zwar in zweierlei Weise. Einerseits,
in dem es die Argumente einfach in der Reihenfolge durchreicht,
wie sie in der Datenbank stehen. Und im anderen Falle
, das ist die Argumente einfach umdreht. Also wo Forn X steht,
steht hier vorn Y. Und damit wird erreicht,
dass ich es einmal über diese Regel ableiten kann,
so wie es in der Datenbank steht.
Paul und Anne sind Zwillinge und über die zweite Regel kann
ich es ableiten, Anne und Paul sind Zwillinge,
weil ich die Argumente einmal vertauscht habe
Ja. Und dann, das ist also eine faktenbasierte Modellierung.
Ich gebe eine Regel an, die auf Fakten zurückgreift,
die dritte Variante geht nur manchmal, aber im Prinzip natürlich auch.
Ich kann versuchen, eine Art wissensbasierte Modellierung aufzubauen,
indem ich versuche, allgemein zu definieren, was ist eigentlich ein Zwillingspaar.
Und ein Zwillingspaar ist hier eben definiert als zwei Personen,
X und Y,
die die gleiche Mutter haben und am gleichen Tag
geboren worden sind
Ja, natürlich, jetzt können sie sofort kommen und sagen,
hahahaha und was ist am Mitternacht und so weiter und so fort.
Jede dieser Definitionen hat, das ist genau das,
was sie vorhin gesagt habe, zu jeder realen Relation gibt es Ausnahmefälle.
So ist die Welt. Wir kommen nicht ohne Ausnahmen
aus. Das ist eben eine sehr generelle Definition,
die kennt keine Ausnahmefälle. Da muss man sich überlegen,
ob man damit leben will oder ob man jetzt wieder noch
Ausnahmeregeln für den Tag vor oder nach dem Jahreswechsel einführen will.
Kann man machen. Dann wird es so ein bisschen komplizierter.
Warum ist diese Definition jetzt symmetrisch? Das ist natürlich
die Frage
Oder warum ist die Relation, die da berechnet wird, symmetrisch? Ja,
dieselbe Definition erhalten, die muss man da tauschen,
werden die beiden Pflegekatale im Kurzzeitpunkt unterscheiden,
sich in Unterschied auch als erste Stimmung zu verstehen,
dass man da kompliziert ist.
Ebenfalls dann mit der zweiten Stelle. Genau,
das heißt also,
die gesamte Definition hier ist bezüglich von X und Y
symmetrisch und dann erbt diese Relation Zwilling von dieser Symmetrie
der Definition die Eigenschaft,
dass die Argumente vertauschbar sind
Jetzt können wir uns natürlich fragen, muss man wirklich das
mit diesem Hilfsprädikat machen? Das ist ja ein bisschen ärgerlich,
dieses ZV, ja, das sieht ja unschön aus.
Hinzu kommt, dass der Mathematiker, also dieses Jahr,
dass der Mathematiker es ja auch nicht machen würde.
Der Mathematiker würde das so hinschreiben, indem er sagt,
also Paul und Anne sind Zwillinge und wenn XY an einen umgekehrt,
wenn XYX-Zwillinge sind, dann ist auch XY das Paar.
Ein Zwillingspaar
So, wenn wir das also so verwenden und dann testen,
ja, wir müssen das immer testen, vollständig instanziert.
Also wir testen, ist Paul und sind Paul und Anna
ein Zwillingspaar und wir kriegen Truhe heraus, na schön.
Jetzt kommt der entscheidende Punkt, wenn wir diesen Aufruf machen,
der ist trivial. Der wird also durch diese erste Klausel
hier beantwortet. Wenn wir es umgekehrt aufrufen,
liefert der Fakt ja natürlich kein Ergebnis,
sondern wir müssen zu der Regel kommen,
die Regel ruft Zwilling von wieder auf, vertauscht aber dabei die Argumente.
Das heißt, jetzt haben wir es zurückgeführt auf die Anfrage,
die wir hier oben schon hatten.
Und die wird mit dem ersten, mit der ersten Klausel,
mit diesem Fakt hier positiv beantwortet.
Daher auch hier das gewünschte Ergebnis. Sieht doch alles bestens
aus, ja
Ja, ist, wenn man jetzt eine Anfrage machen kann,
das Zwilling von allen nochmal alles.
Eine Möglichkeit, die Probleme tauchen an zahlreichen Stellen auf,
die einfachste Fall ist schon,
wenn ich mir die Relation aufzählen lassen will.
Also, wer steht alles in der Zwillings-Fond-Relation? Dann stelle
ich erstmal die fest, ich kriege unendlich viele Ergebnisse.
Das ist der erste Fall, den wir haben,
wo die dedudationelle und die operationale Samantik auseinanderfallen.
Wir würden hier demotationell, also so wie es der Mathematiker sieht,
nämlich genau zwei Elemente erwarten. Paul und Anne,
Anne und Paul, was wir tatsächlich kriegen, ist,
dass zyklisch beliebig viele Variablenbindungen erzeugt werden.
Das System ist blind für die Tatsache,
dass es hier immer wieder das Gleiche tut.
Ja. Das System ist fest schlecht, kommt jetzt schon
mal. Gucken wir uns zum Schluss an.
Sie können sich schon mal auf die Frage vorbereiten,
ob ich auf diese Art und Weise das Halteproblem der Thuring-Maschine lösen kann.
Das ist nämlich genau das, worauf es hier auch hinausläuft.
Das kriegen wir später. Das müssen wir uns jetzt nicht
damit befassen. Wir beobachten einfach im Augenblick mal nur,
da gibt es eine Differenz.
Es ist plötzlich nicht mehr das Gleiche,
ob wir über die dedotationelle Semantik sprechen oder über die
operationale Semantik sprechen
Die Berechnung liefert etwas anderes als die demotationelle Semantik erwarten lassen würde.
Wir können es, sie hatten vorgeschlagen,
Anne Anne zu nehmen, läuft genau auf das Gleiche hinaus.
Ich habe es hier mit einem unbekannten Objekt gemacht.
Also hier hinten taucht jetzt Karl auf. Und wir haben
ein vollständig instanzuierten Aufruf. Das ist bitteschön zu bemerken.
Und wir kriegen den Effekt, dass unser System nicht wieder zurückkommt.
Dass es also in einen Zyklus gerät und endlos lange darin berechnet.
Was passiert hier? Das ergeht mit dieser Anfrage,
sind Paul und Karl, ist das ein Zwillingspaar?
Geht er in diese Definition hinein
Der Fakt liefert natürlich kein Ergebnis. Dann vertauscht er eben
die Argumente und guckt, ob Karl- und Paul-Zwillingspaar sind.
Dazu sagt der Fakt aber auch nichts aus. Also wäre die Argumente
wieder vertauscht und geguckt, ob Paul Karl ein Zwillingspaar ist.
Das liefert auch kein Ergebnis. Also wenn die Argumente vertauscht
und es wird das Gegenstück wieder geprüft.
Das heißt, und dieser Prozess wird unendlich lange wiederholt.
Auch hier also wieder eine Differenz zwischen dennotationeller und operationaler Semantik.
Vorhin war es nicht so schlimm. Da hatten wir immer
noch die Kontrolle am Prompt. Da konnten wir sagen,
okay, mehr Ergebnisse wollen wir nicht.
Da hätten wir zum Beispiel sagen können,
gib mir nur die ersten zehn Ergebnisse und dann brich ab.
Hier können wir das nicht sagen. Wir kommen gar nicht
wieder zur Interaktion. Das System spielt ab und wandert ins Unendliche
Und wir würden also denotationell erwarten,
es kommt ein No heraus über die Zwillingseigenschaft von Paul und Karl,
wissen wir nichts, oder eigentlich ein False,
das ist auch noch ein Überbleibsel einer früheren Systemvariante,
operational ergibt sich, dass die Suche nicht terminiert.
Und der Verdacht liegt natürlich nahe, das Einzige,
was wir geändert haben gegenüber der relationalen Welt, ist,
dass wir jetzt rekursive Spezifikationen von Relationen zulassen und dass
genau das der Grund für die Terminierungsprobleme ist.
Und der Ausweg ist eben, wir müssen es vermeiden,
dass wir eine solche unbeschränkte Rekursion einführen,
Dass wir blind links das Prädikat wieder aufrufen,
nur dass wir eben die Argumente vertauscht haben.
Wir müssen dafür sorgen, dass es gezwungen wird,
die Validität dieser Regel an Fakten zu überprüfen.
Und das können wir nur dadurch erreichen,
indem wir es frühzeitig zwingen, auf die Fakten zu schauen.
Und das machen wir hier, indem wir also sagen,
wir führen das unmittelbar auf diese Fakten zurück.
Und dann sind wir auf der sicheren Seite und können die
Terminierung tatsächlich erzwingen. Was auch eine wichtige Lektüre ist,
eine wichtige Lektion ist, die man hier lernen kann,
Das Testen dieser positiven Beispiele hat uns das Problem nicht gezeigt.
Und das ist typisch für das Halteproblem der Touring-Maschine, wenn das Terminierungsproblem auftritt,
dann tritt es nicht im positiven Fall auf, sondern im negativen Fall.
Oder genereller gesagt, im komplementären Fall, und den haben wir hier genau.
Also positive Tests bringen uns das Problem überhaupt nicht ans Tageslicht.
Wir müssen so etwas testen wie etwas, was negativ ist,
wo wir erwarten würden, dass das System sagt,
nein, dazu weiß ich nichts.
In dem Augenblick entdecken wir plötzlich, oh hops,
da gibt es ein Terminierungsproblem,
gegen das müssen wir
etwas machen
Und was wir haben gesehen,
wie wir es vermeiden können, dieses Einführen des Hilfsprädikates,
ist an dieser Stelle tatsächlich die Methode der Wahl.
Das zwingt das System zeitig auf die Fakten zu schauen und
dann wird die unbeschränkte Rekursion vermieden. Oder mit anderen Worten
, es gibt in der Definition gar keine Rekursion mehr.
Also hier ist nirgendwo ein rekursiver Aufruf drin.
Das ist ja rein nur eine Abbildung,
in der relationalen Datenbankwelt würden wir sagen, eine Sicht.
Ich habe eine Sicht definiert. Nichts anderes ist hier passiert
So, damit haben wir den Rekursionsbegriff hier Rekursion, also als Selbstbezüglichkeit einer formalen Struktur.
Die werden wir in verschiedener Weise kennenlernen, jetzt,
also die zweite Form ist ein Datentyp wird durch sich selbst definiert,
das kriegen wir als nächstes im zweiten Schritt dann,
wir sind noch im dritten Schritt,
wir sind jetzt aus dem zweiten, wir gucken uns jetzt nur an,
eine Prädikatsdefinition wird auf sich selbst zurückgeführt und das ist das kanonische Beispiel dafür,
um zu definieren, was ein Zwilling ist,
greifen wir auf die Zwillingsdefinition zurück.
Und eine solche unbeschränkte Rekursion,
die wir auch hier in dem Escher-Belt haben,
die bringt uns eben
das Terminierungsproblem ins Haus
Zweite Eigenschaft, Transitivität, Transitivität ist ein bisschen komplizierter als
die Symmetrie. Transitivität heißt immer, wenn ich von X
nach Y komme und ich komme von Y nach Z,
dann komme ich auch von X nach Z.
Also die typische Erreichbarkeitsrelation über einem Graphen beispielsweise.
Oder allgemeiner eben, wenn, gilt das XY in einer
Relation P stehen und YZ in der Relation P stehen.
Da muss auch gelten, dass X und Z in
der Relation stehen. Das hat man,
da gibt es ganz viele Anwendungen in der Informatik,
eine der einfachsten sind terminologische Wissensrepräsentationen,
all das,
was immer unter Ontologie läuft heutzutage
Da ist es eine SA-Relation, dass sie also Dinge auseinander definiere.
Ein Stuhl ist ein Möbelstück,
ein Möbelstück ist ein Gegenstand und ein Einrichtungsgegenstand und so weiter.
Hier ist es für eine Teil von Hierarchie gemacht.
Ich erkläre also immer, aus was sich ein Konzept zusammensetzt.
Also ein Auto setzt sich aus sowas zusammen, was ein Rad ist,
was ein Motor ist und möglicherweise noch ein paar mehr Sachen.
Und ein Rad setzt sich aus der Felge zusammen und möglicherweise noch ein paar mehr Sachen.
Der Motor enthält Kolben, Ventile, Zündkerzen und so weiter.
Und ich möchte jetzt in dieser Wissensbasis natürlich schließen können,
hat eine Felge irgendetwas mit einem Auto
zu tun
Und das kann ich nur dadurch regeln, dass ich feststelle,
ja, die Felge ist Teil des Rades.
Das Rad ist Teil des Autos.
Also ist auch die Felge Teil des Autos.
Das ist die Form des Schließens, die ich hier realisieren will.
Und das müssen wir jetzt wieder einbauen. Wir sind gewarnt,
dass wir mit unbeschränkter Rekursion möglicherweise Probleme hervorrufen.
Und dass es nützlich sein kann, immer sofort auf die
Fakten zu gucken. Und das machen wir hier auch.
Wir definieren also die Teil von Relation. Einerseits,
indem wir direkt auf die Daten gucken,
das heißt hier
immer unmittelbares Teil von
Und die Argumente einfach eins zu eins übergeben.
X auf der ersten Argumentstelle Y auf der zweiten Argumentstelle.
Und die zweite Klausel stellt uns jetzt diesen transitiven Schritt her,
dass ich den nächsten Schritt weitergehe,
die guckt aber auch erst mal auf die Fakten und sagt,
ja, X ist Teil von Z,
wenn es einen Fakt darüber gibt,
dass X unmittelbares Teil von irgendetwas Drittem ist.
Und dann muss ich noch nachweisen,
dass dieses dritte Y nämlich Teil von Z ist.
Das ist jetzt nicht mehr unmittelbares Teil von,
sondern das ist beliebiges Teil von,
ja.
Das ist jetzt mal wieder so
Ja. Ja, 83. Frühkonsult einlesen kann, die Möglichkeit,
um mitzuteilen, dass diese hilfsverlationen nicht direkte zum Beispiel bei der einen Sonderindustrie.
Ja, es gibt ein, es gibt auch ein Modulsystem,
das wäre hier aber nicht behandeln,
wo ich nach außen hin wie üblich deklarieren kann,
was ist nach außen sichtbar und was ist nach außen nicht sichtbar.
Ich kann Module definieren wie in jeder anderen Programmiersprache auch und
das geht hier auch. Das ist, das ist ein,
auch ein etwas unschöner Effekt oder einer der großen Nachteile gegenüber der funktionalen Programmierung,
wo ich an diesen Stellen auch mit, mit Lamde ausdrücke,
mit unbenannten Funktionen arbeiten kann.
Ich muss dem Kind hier immer einen Namen geben,
damit ich es verwenden kann
Dieser Name geistert dann natürlich irgendwo rum, ruft möglicherweise Kollisionen hervor.
Und dann ist natürlich so ein Modulsystem immer die Methode der Wahl,
dass ich sage, okay, ich kapsel das jetzt in ein Modul ein,
nach außen über die Schnittstelle sind nur folgende Prädikatsaufrufe sichtbar.
Alles andere ist modulintern und nach außen überhaupt nicht sichtbar.
Gut, wir nehmen diese Definition und Sie sehen schon,
jetzt wird es ein bisschen aufwendiger. Wir testen vollständig instanziert,
ist die Felgeteil des Autos, mit der Anfrage gehen wir ins Rennen.
Es ist schön, diese Teil von Relation hat nur zwei Klauseln. Das heißt,
der Baum ist ein Stelle nur binär verzweigend, immer dann,
wenn wir das an den Fakten prüfen muss,
dann ist er natürlich so, hat er so viele Verzweigungen,
wie wir Fakten über unmittelbares Teil von in der Datenbank drin haben.
Also als erstes müssen wir gucken, gibt es einen,
oder fehlen ein paar Strichelchen, aber nein, fehlen gar nicht.
Können wir mit der ersten Regel die Anfrage, ist die Felgeteil des Autos,
abbilden auf eine, ist unmittelbare Teil von Anfrage.
Wir instanzieren dann X1 mit F und X, sorry,
X1 mit F und Y1 mit A,
übernehmen diese vaiablen Bindung in den Körper der Klausel und kriegen die Anfrage,
ist die Felge unmittelbares Teil des Autos.
Damit gehen wir in die Faktensammlung, Das ist nur eine Faktensammlung,
da gibt es keinen Fakt darüber, das scheitert alles.
Das heißt, wir müssen zurück zu diesem Entscheidungspunkt und hier die zweite Klausel bemühen.
Und das ist jetzt der transitive Schritt. Jetzt udifizieren wir
den Kopf der Klausel, wieder mit der Anfrage.
Wir binnen X1 an F,
Z1 an A und müssen mit dieser vajablen Bindung den Körper der Klausel,
was jetzt ein komplexes Ziel ist, kein einfaches mehr aktivieren.
Das heißt, wir müssen als erstes prüfen,
ob X1 unmittelbares Teil von irgendetwas anderem ist
X1 ist also unser Felge, also wir prüfen,
ob die Felge, unmittelbares Teil von irgendetwas anderem ist.
Das ist das erste Teilziel, das wir jetzt abgearbeitet wird.
Das liefert ein Ergebnis, und zwar mit der Variablenburg für Y1,
das Rad ist unmittelbares Teilziel der Felge.
Damit haben wir eine Variablenbindung für Y1 und können mit der
jetzt in das zweite Teilziel gehen, das haben wir erfolgreich abgearbeitet.
Wir können mit hier in die Abarbeitung hineingehen und können jetzt
dort testen, ob denn das Rad ein Teil des Autos ist
Kein unmittelbares Teil, sondern ein Teil des Autos.
Also möglicherweise über eine transitive Schrittfolge. Das führt uns wieder
zu der ersten Regel. Die erste Regel bildet es eins
zu eins auf das Hilfsprädikat mit dem unmittelbaren Teil von ab.
Wir kriegen die vaiablen Bindung X2SR Y2SA. Was sie
auch bemerken sollten, hier, diese Regel haben wir,
ich führe immer neue Variablen ein.
Wann immer eine Klausel aktiviert wird, gibt es neue Variablenbezeichner.
Und der Bezug zwischen den verschiedenen Ebenen wird nur über
solche Chorreferenzgleichungen hergestellt
Haben wir hier irgendwo eine? Die haben wir dummerweise keine,
aber Beispiele dafür kriegen wir gleich noch. Ja,
ich muss also jetzt gucken,
ob denn das Rad unmittelbares Teil des Autos ist und das ist,
da gibt es tatsächlich einen Fakt darüber, das ist erfolgreich.
Das heißt, die Vagablenbindung, nein Quatsch,
gar keine Vagablenbindung über die Kette.
Die Felge ist Teil des Rades und das Rad ist Teil
des Autos. Das sind die beiden zentralen Elemente,
habe ich transitiv abgeleitet, Felge und Auto stehen in
der Teil von Beziehung
So, wir könnten dann den Test machen,
wenn wir hier noch nach, also in dem Falle,
nein, macht nichts, wir haben keine Variablen drin,
weitere Ergebnisse gibt es nicht.
Wir gucken uns noch weitere Anfragen an. Also ist,
wir hatten ja vorhin, dass den kritischen Fall,
wir müssen negative Sachen testen. Die Felge ist ja Teil
des Autos, das wussten wir auch vorher schon.
Wir müssen jetzt testen, ob es denn auch für negative Fälle gilt.
Hier sind also erstmal noch, Moment, hatte ich
Eine Bremse taucht doch ja gar nicht auf. Das ist doch
Unfug. Hier sind zwei verschiedene Varianten hinzugekommen. Die Datenbank,
die hier steht, die hat dummerweise mit dem Beispiel hier nichts zu tun.
Das muss ich nochmal äh ändern. In der Datenbank gibt es
keine Informationen über eine Bremse. Wie jeder gute Autofahrer weiß,
ist die Bremse eher hinderlich beim Autofahren als förderlich.
Das heißt, hier müsste eigentlich ein No herauskommen oder
ein False herauskommen.
Das ist leider Gottes falsch
Heißt aber im Wesentlichen auf dem negativen Beispiel terminiert es auch.
Das ist uns ja wesentlich, dass wir auch mit
negativen Beispielen testen, ob das ganze Terminierungssicher ist.
Wir können auch partiell uninstanziert aufrufen,
also von was ist die Felge alles ein Teil und wir kriegen
dann tatsächlich den Pfad von der Felge nach oben bis zur Spitze der Hierarchie.
Also ist Teil des Rades und das Rad des Teil des Autos.
Das beantwortet, wir können auch umgekehrt fragen,
was ist Teil des Rades gegeben?
Die Datenbank haben wir nichts anderes als die Informationen.
Es ist eine Felge. Oder aber wir können uns
die Relation vollständig aufzählen lassen und wir kriegen dann die tatsächlich
eine endliche Aufzählung aller Pfade durch diesen Baum.
Und auch das war eine kritische Anfrage vorhin bei der Symmetrie,
wenn wir das unestanziert aufgerufen hatten,
dann gab es eben immer fort dieses Austauschen der Konstanten.
Während hier passiert nichts Ähnliches. Es scheint also eine Definition
zu sein, die Terminierungssicher ist, die vollständig ist,
dass sie uns alle Ergebnisse liefert. Gut,
in der In der Übung werden wir dann die analoge Frage,
die sich hier jetzt natürlich genauso stellt,
können wir dich auf dieses Hilfsprädikat verzichten?
Also müssen wir wirklich diese Trennung machen zwischen Teil von und unmittelbarem
Teil von? Diese Frage wird dann Gegenstand der Übung sein,
wo sie sich mal überlegen können, was passiert,
wenn man das weglässt?
Ob es nicht eine Möglichkeit gibt durch geschickte Anordnung der Klauseln
beispielsweise zu erreichen, dass das Ding doch terminierungssicher wird,
auch wenn wir kein solches Hilfsprädikat verwenden
Ich hatte gedacht, vorhin ist es mal gegangen,
jetzt geht es ja nicht mehr oder wie ist das hier?
Oder? Ach so, das ist genau eine Frage.
Ja, das ist noch die Sommerzeit. Okay, gut.
Okay, aber ansonsten, der Minutenzeiger ist einigermaßen verlässlich.
Dann richte ich mich nach dem. Gut,
funktionale Abhängigkeit, das ist auch etwas,
was in der relationalen Datenbankwelt
eine große Rolle spielt
Wenn es beispielsweise darum geht, Datenbanken zu normalisieren,
dann will ich immer sicherstellen,
dass funktionale Abhängigkeit für den Schlüssel eines Tupels gilt.
Die Terminologie ist ein bisschen anders, insbesondere habe ich es versucht,
hier deutlich zu machen, die Terminologie der relationalen Datenbankwelten,
also eine Relation ist vom Typ 1 zu m oder vom Typ M21 ist leider Gottes mehrdeutig.
Es gibt Leute, die benutzen eins zu M dafür,
wenn das erste Argument eindeutig sein soll.
Es gibt Leute, die benutzen 1 zu M,
wenn das zweite Argument eindeutig sein soll. Das heißt also,
aus der reinen Notation kann ich nie so richtig entnehmen,
welche Variante eigentlich gemeint ist. Deshalb werde ich hier dann
immer davon reden, eine Relation ist funktional in einem Argument.
Und damit ist es eindeutig. Also beispielsweise zu sagen,
eine Relation ist funktional im ersten Argument,
wenn denn gilt, wann immer ich zwei Tupel habe,
XY und ZY, dann gilt für die funktionale Forderung,
dass auch X und Z
gleich sein müssen
Während es in einem zweiten Argument eindeutig sein soll,
dann gilt das eben für die zweite Argumentstelle.
Also es geht immer um darum,
dass eine Argumentposition sich eindeutig aus allen anderen ergibt.
Das ist das wesentliche Eigenschaft. Und das ist dann eben,
wenn diese von diesem Typ ist, dann ist die Eigenschaft gegeben,
dass sich der Wert X als Funktion aus Y berechnen lässt.
Eindeutig eben. Und das sind natürlich Spezialfälle allgemeiner M2N-Relationen
und wir müssen uns jetzt angucken,
wie machen die sich im Prologsystem bemerkbar
In der Realität haben wir eben Beispiele für Funktionalität
im ersten Argument bisher bei der Mutter von Relation gehabt,
die Mutter sollte immer eindeutig gegeben sein für ihre Töchter.
Bei der Alter von Beziehung sollte das ebenfalls sein,
es sollte nicht sein, dass eine Person zwei unterschiedliche Altersangaben hat,
dann liegt Inkonsistenz vor.
Wir haben auch Beispiele für die M-zu-1-Relation schon gesehen,
so wie sie spezifiziert waren,
ist unmittelbares Teil von eindeutig im zweiten Argument,
also irgendein Teil ist immer eindeutig Teil eines anderen Teils
Ob das in der Realität immer durchzuhalten ist, darüber kann man diskutieren.
Aber so ist es hier erst mal definiert.
Oder eben auch eine Stadtlicht immer eindeutig in einem Land.
Auch das ist nicht notwendigerweise überall gegeben.
Da gibt es genügend viele Streitfälle auf der Welt,
wo Städte mitten durchgeteilt sind und dann plötzlich in zwei Ländern liegen.
Aber mit solchen Vereinfachungen müssen wir eben wie immer in der Informatik leben.
Und wir müssen uns zur Rechenschaft darüber ablegen,
ob die Vereinfachung für den betreffenden Fall angenommen werden kann.
Also ob die negativen Auswirkungen vernachlässigbar sind oder ob wir nicht
die Fälle tatsächlich genauer betrachten müssen,
wo die Ausnahmen vorliegen
So, wenn wir eine Prädikatsdefinition aufschreiben, dann ist die im allgemeinen Fall
immer vom Typ M zu enden. Es gibt nichts im System,
genauso wenig wie in einer relationalen Datenbankwelt,
wo das System sagt, halt, da liegt auch doch,
das System macht es im Falle,
im Falle der Schlüssel macht es das relationale Datenbanksystem sogar,
aber außer den Schlüsseln an keiner anderen Stelle und so
ist es hier dann auch
Wenn Sie vom Typ M2N sind, dann heißt es,
bei eindeutigen Relationen wird auch bei der,
wenn ich die Anfrage stelle, immer nach den Alternativen gesucht.
Wenn ich also nach einem Ergebnis für Mutter bereits bekommen habe,
dann wird weiter nach der zweiten Mutter gesucht.
Das System weiß nicht, dass Mutter eindeutig gegeben ist.
Oder eben, wenn ich bereits die Altersangabe für eine Person habe,
dann sucht das System auf Anforderung blind nach einer zweiten Altersangabe.
Und da wir gesehen haben, das kann unter Umständen Terminierungsprobleme hervorrufen.
Wenn ich also ein Ergebnis schon habe und dann blind links weiter suche,
dann komme ich nämlich genau in den komplementären Fall,
den ich mit No beantworten muss oder mit False,
wo es keine Ergebnisse mehr gibt.
Und wir hatten es gesehen,
für den positiven Fall kann ich sehr oft die Terminierung sicherstellen.
Wenn das Problem auftaucht, dann taucht es im komplementären Fall
auf. Nämlich dann, wenn ich das Negative untersuche.
Und nach dem letzten Suchergebnis bin ich immer in der Suche
nach dem negativen Fall. Immer. Das heißt,
wenn ich vollständig die Ergebnisse haben will und den gesamten Suchraum durchmustere,
laufe ich zwangsläufig in ein Terminierungsproblem hinein.
Ich kann bestenfalls hoffen, dass sich das Terminierungsproblem Erst ergibt,
nachdem ich das gewünschte Ergebnis habe.
Und wenn ich dann eben sicherstellen kann,
dass ich nach dem ersten Ergebnis aufhören kann zu suchen,
dann werde ich überhaupt nicht mit dem Problem konfrontiert.
Gut, also es gibt zwei Probleme. Es kann unter
Umständen unnötigen Suchaufwand hervorrufen. Das ist etwa bei der Mutter
von Relation der Fall. Auch wenn ich weiß,
es gibt keine zweite Mutter, ich muss sie trotzdem suchen.
Oder aber es kann Terminierungsprobleme bei rekursiven Definitionen hervorrufen.
Da gibt es einen Ausweg, das ist der sogenannte Cut,
womit man die Suche steuern kann, wo man sagen kann,
Wenn ich an einer bestimmten Stelle in der Suche angekommen bin,
brich ab, suche nicht weiter.
Weil das ein bisschen kompliziert ist, gucken wir uns das
auch später an. Die Sachen müssen wir jetzt nicht betrachten.
Die Botschaft ist hier nur, jawohl,
bei solchen eindeutigen Relationen möchte man gern diese Eigenschaft ausnutzen.
Man kann sie ausnutzen im allgemeinen Fall sind die Relationen aber nicht eindeutig.
Also M-2N-Relationen. Ja, letzte Eigenschaft ist die Reflexivität.
Reflexiv ist eine Relation, immer wenn für jedes Element gilt,
dass es mit sich selbst in dieser Relation stellt
Da sind Beispiele eben die Gleichheit. Jedes Element ist gleich zu sich selbst.
Im Falle der Logikprogrammierung wird es auch die Unifizierbarkeit sein.
Ein Term ist immer mit sich selbst unifizierbar. Und wann
immer ich jetzt in einer Relation auf die Unifikation beispielsweise zurückgreife,
dann erbt die Relation von der Unifizierbarkeit die Reflexivität.
Hier ist das Spiel umgekehrt. Das möchte ich nicht immer
haben. Standardmäßig ist eine, wenn es also irgendwo eine
Unifikation in der Definition auftaucht, ist das Ergebnis ebenfalls reflexiv.
Das möchte ich nicht immer haben. Ein Beispiel davon ist
die Schwester von Relation
Wenn ich die also naiv definiere, indem ich sage,
Schwester von, also x ist Schwester von Y,
wenn beide Kind eines gemeinsamen Elternteils sind.
Und natürlich muss eine Schwester weiblich sein. Man sieht hier keine Unifikation,
aber tatsächlich taucht eine auf. Sie taucht nämlich genau dort auf,
wo ich hier über das Z die Co-Referenz herstelle.
Eine Chor-Referenz hatten wir schon gesagt,
wenn denn eine valiable, auf eine Variable trifft,
und das ist hier der Fall,
dann wird vajablen Sharing hergestellt und das ist immer gleichbedeutend mit
einer Unifikation der entsprechenden Werte
Von dort ist also hier drin in dem Körper der Klausel
eine Unifikation versteckt. Und wenn ich das jetzt benutze und beispielsweise,
ach so, Jarek, es kommen Fakten dazu,
mit Personen, Kind von und mit Angaben männlich, weiblich.
Und ich mache jetzt die Anfrage, ist, wer ist die Schwester von Susi?
Dann gehe ich in diese Relation hinein. Ich muss ein Kind,
ich muss finden, Moment, was ist instanziert?
Das Zweite, das instanziert. Ich X wird nicht instanziert.
Z wird auch nicht instanziert. Ich muss ein Eine zweite,
eine weitere Person finden und diese Suche nach einer weiteren Person
geht in die gleiche Datenbankkind von oder in das gleiche Prädikat,
in die gleiche Prädikatsdefinition für Kind von hinein,
wie dieses erste Teilziel.
Hier ist nirgendwo spezifiziert und es würde auch schwer sein,
das zu tun, dass die Bindung für Y jetzt eine andere sein muss als die Bindung für X.
Ja, das heißt, dann probieren Sie es mal.
Das können Sie machen, wenn es zu spät ist,
aber nicht vorher. Es ist die Antwort auf die Frage,
die ich gleich stellen werde,
aber wir gucken uns erstmal
die Definition an
Die, es wird also hier ein, aus dieser Relation Susi Anne
herausgesucht und dann wird mit dem zweiten Teilziel aus dieser Relation das Pasusi Anne rausgesucht.
Sie erfüllen beide die Korreferenzeigenschaften, dass Anne nämlich das Elternteil
für Susi und für Susi ist und Susi ist auch weiblich.
Das heißt, das erste Ergebnis ist Susi. Wenn ich nach Alternativen frage,
muss ich nach weiteren Kindern von Anne suchen, Moment,
muss ich nach weiteren Kindern von Anne suchen und da kriege ich die Jane hier ins Spiel,
die kriege ich als zweites Ergebnis ausgegeben,
weil sie auch weiblich ist, wenn ich wieder nach Alternativen suche,
kriege ich den Karl geliefert,
aber der ist nicht weiblich, deshalb fällt das weg,
dann muss ich mich noch nach weiteren Alternativen für das erste Teil zu kümmern und weitere Alternativen für das erste Teil zu,
gibt es nicht, weil Susi an der zweiten Position hier nirgendwo auftaucht.
Das heißt, das sind die Einzelergebnisse,
die ich bekomme
Und das Unschöne daran ist eben, die Relation ist reflexiv.
Susi ist ihre eigene Schwester. Und das will man
im allgemeinen Verständnis von Schwesternschaften natürlich nicht haben.
Das muss man ausschließen. Und jetzt kommt die Antwort,
die Sie schon auf die Frage gegeben haben,
die noch gar nicht gestellt war.
Wie kann ich es verhindern? Und ich kann es verhindern,
indem ich hier oben fordere,
dass X nicht das Gleiche sein darf wie Y. Oder mit den Worten der Logikprogrammierung,
dass die beiden nicht unifizieren dürfen.
Und dass die Forderung auf Nichtunifizierbarkeit, da gibt es den Operator dafür,
ich glaube, der ist in der ersten Übung schon aufgetaucht.
Das ist genau dieser hier
Erfordert, dass zwei Therme, die die rechts und links stehen, nicht unifizierbar sein sollen.
Und wenn ich jetzt also hier hinten hinzufüge, X,
nicht unifizierbar Y, dann wird diese Lösung ausgeschliehen.
Dann scheitert also dieses Paar Kind von Anne, nee,
Susi Anne, Susi Anne,
da ist nämlich genau der Wert von X,
gleich dem von Y. Und deshalb kommt ja dieses Ergebnis zustande.
Allerdings sollte man eben beachten,
man kann diesen Operator erst dann anwenden,
wenn ich tatsächlich ein,
wenn die Variablen instanziert sind
Also diesen Operator auf noch nicht instanzierte Variablen anzuwenden,
das funktioniert nicht. Also ich kann nicht sagen,
ich nehme hier die erste Klausel, also Susi Anne,
fordere dann, dass das Y ungleich Susi sein muss.
Das geht nicht. Ja, also das Prolog-System kann nur
positive Forderungen verarbeiten, niemals negierte. Also es kann nicht
verwalten, welche Dinge alle nicht miteinander unifizierbar sein sollen.
Wenn man das haben will, braucht man ein Constraint-Setisfiction-System,
das gibt es als Erweiterung der Logikprogrammierung,
behandeln wir hier aber nicht mehr
Gut, letzter Schritt ist, wir gucken uns jetzt ein Anwendungsbeispiel an,
wo wir eben eine kleine Landkarte gegeben haben.
Es gibt Erreichbarkeitsrelationen, die sind hier spezifiziert als Connection,
von Hamburg kann man nach Berlin, von Hamburg kann man nach Hannover,
von Hamburg haben wir nach Bremen.
Wir wissen, diese Spezifikation ist immer asymmetrisch. Wenn wir also Verbindungen haben,
wo wir annehmen können, wenn wir von Hamburg nach Bremen kommen,
dann kommen wir auch von Bremen nach Hamburg,
dann müssen wir etwas explizit tun,
um diese Verbindung herzustellen.
Und wir wissen auch schon,
was wir tun können
Also das ist erstmal der Effekt. Wenn wir nur die Faktensammlung nehmen,
die wir bisher hatten, dann ist eben Bremen von Hamburg
aus erreichbar, aber Hamburg von Bremen aus nicht.
Und der Trick, den wir anwenden müssen, ist eben,
wir müssen es symmetrisch machen. Das heißt,
wir müssen jetzt hier einen Brepper außen drumherum schreiben, der sagt,
eine Erreichbarkeit, eine symmetrische Erreichbarkeit, wird eben dadurch hergestellt,
dass sich entweder auf die direkte Erreichbarkeit zurückgreife oder aber die Argumente vertausche und die Umkehrrichtung damit mit ins Spiel bekomme.
Und dann haben wir genau das gewünschte Verhalten,
das ist jetzt nicht sonderlich überraschend,
wenn ich von Hamburg nach Hannover komme,
dann gibt es darüber einen zack in der Datenbank,
wenn ich von Hannover nach Hamburg komme,
weil dann kommt auch ein positives Ergebnis heraus.
Aber das wird hier über diese Regel vermittelt und nicht über die erste.
Ich vertausche also die Argumente und schicke dann die vertauschte Anfrage.
Hamburg, Hannover, wieder ins Rennen und die liefert über diesen Fakt ein Ergebnis.
Das war also der einfache Teil. Die zweite Eigenschaft,
die ich bei der Erreichbarkeit habe, oder die ich haben möchte,
ist natürlich die Transitivität und die Transitivität,
dass ich also über mehrere Zwischenstationen das Ziel erreichen kann,
da hatten wir ja dieses Pattern gesehen,
entweder ich bilde jetzt die Erreichbarkeit,
die transitive Erreichbarkeit direkt auf die unmittelbare Erreichbarkeit ab oder ich bilde die transitive Erreichbarkeit ab,
indem ich direkt ein drittes Ziel ansteuern kann und dass dann eine transitive Erreichbarkeit von diesem Zwischenziel zum Endziel tatsächlich gibt.
Wir können auch das wieder testen und kriegen dann eben heraus,
komme ich nach Düsseldorf und da kriegen wir tatsächlich jetzt dreimal,
drei Antworten, wo wir jeweils nach Alternativen fragen können.
Das heißt, es gibt drei Möglichkeiten von Hamburg nach Düsseldorf
zu kommen. Wir können uns das mal versuchen,
an der Datenbank nachzuvollziehen.
Ich hoffe,
die Stimmen überein
Von Hamburg nach Düsseldorf kommen wir eben, indem wir nach Berlin fahren,
von Berlin nach Hannover und von Hannover nach Düsseldorf.
Das ist dieser Weg hier. Wir können von Hamburg nach Hannover fahren,
das ist die Abkürzung, warum wir bei Berlin nach Hannover und dann nach Düsseldorf.
Oder wir können über Bremen, also von Hamburg nach Bremen
und von Bremen nach Düsseldorf fahren, das ist dieser Weg.
Das sind die drei Antworten, die wir dort kriegen,
ohne dass wir die genauen Variablenbindungen mit oder den Weg genannt bekommen,
aber wir sehen wenigstens, es gibt drei Möglichkeiten,
dahin zu bekommen, wir können auch die Fragen,
wohin kann ich von Hamburg aus alles fahren?
Und dann kommt eben nach Berlin,
da gab es eine direkte Verbindung,
nach Hannover gibt es eine direkte Verbindung nach Bremen,
gibt es eine direkte Verbindung, dann kann ich wieder nach Hannover fahren,
nämlich über den Umweg Berlin.
Das heißt, dieses Ergebnis ist jetzt über den transitiven Schritt
hergestellt, dass hier oben ist über den Fakt hergestellt.
Hier bin ich jetzt also über Berlin gefahren, dann kommt die drei Düsseldorf-Varianten,
die war hier oben schon mal abgetestet haben und weitere Ergebnisse gibt es nicht.
Ja, und die hohe Schule besteht jetzt darin,
dass man das tatsächlich miteinander verbindet,
indem man hier oben die Symmetrie herstellt durch Vertauschen der Argumente.
Also jetzt haben wir eine Erreichbarkeit, die sowohl symmetrisch als auch transitiv ist.
Die geht eben entweder direkt in die Faktensammlung oder mit vertauschen Argumenten in die Faktensammlung.
Und die Transitivität wird eben über diese beiden Klauseln hergestellt,
wobei wir auch hier wieder beide in der Faktensammlung die Argumente vertauschen müssen.
Also es kann sein, dass sich das erste Teilziel so erreiche,
wie es in der Con-Datenbank angegeben ist,
oder aber eben entgegen der Pfeilrichtung.
Das ist die vierte Klausel
Und jetzt kann ich das also testen,
ich kriege ein erstes Ergebnis, jawohl,
ich kann nach Bremen fahren, von Hannover aus,
ich kriege ein zweites Ergebnis,
ich kriege ein drittes Ergebnis und danach schmiert das System ab.
Warum? Ja, jetzt nicht üblich, das geht jetzt zu 14 Minuten ins Wort.
Dann kriegt er ein neues Ergebnis. Ja, letzteres Jahr,
aber zum, ach so, in dem Moment,
was haben wir, was haben wir genau gefragt, sorry?
Na no. Hallo, ich habe, Ich habe die Orientierung,
es stürzt nicht ab, es hängt sich auf.
Ich kann jederzeit über Kontroll C wieder zurückkommen.
Also das muss man auch immer noch fein unterscheiden.
Es ist kein Absturz, der dort passiert. Wo sind
wir denn nie? Hier waren wir. Ach so,
nein, wir haben vollständig instanziert aufgerufen. Ja,
also es ist tatsächlich so, er fährt munter im Kreise.
Die Frage ist nur, warum ist er hier nicht munter im Kreise gefahren?
Bei mir nur diese, die Einrichtung. Genau,
da sind es noch die Einrichtungssäge mit Reizfuß und dann Ja, ich auch.
Ja, also im ersten Fall hatten wir Einbahnstraßen,
die ich nur in einer bestimmten Richtung befahren kann.
Und da war die Frage eben von Hamburg irgendwo hinzukommen.
Und wir sehen, es gibt für diese Anfrage keinen einzelnen Zyklus,
der sich bilden lässt. Irgendwo muss ich immer gegen den
Strich fahren. Während wenn ich die Symmetrie mit hinzunehme,
dann kann ich plötzlich in jeder Richtung fahren und dann kann ich hier
endlos lange im Kreise fahren und auf die Art und Weise neue Möglichkeiten generieren,
ohne jemals ein neues Ergebnis für das gestellte Ziel zu erreichen.
Aber das ist kein Artefakt des Prologsystems mehr
So ist die Welt, ja, in der Welt kann
ich im Kreise fahren. Und ich kann nicht erwarten,
dass mein Programmiersystem ein Problem löst, was in der Welt existiert.
Es kann nur eine Beschreibung der Welt liefern.
Natürlich kann ich hingehen und das geht wieder auf die Frage
der Zyklendetektion hinaus. Ich kann hingehen und versuchen rauszubekommen,
ob ich in diesem Zustand schon mal war und überprüfen,
dass ich in dem Zustand nicht noch mal gerate.
Und ja, man kann dies für Spezialfälle machen.
Wir werden tatsächlich uns diesen Fall angucken. Dafür brauchen wir aber ein Hilfsmittel,
das wir in der Lage sind, uns zu merken,
wo sind wir schon überall gewesen oder auf gut Deutsch,
der Faden der Ariadne muss ausgelegt werden, damit wir wissen,
welchen Teil dieses Labyrinths wir schon besichtigt haben und welchen noch nicht.
Und die Datenstruktur dafür wird wieder die Liste sein und da müssen wir erst mal einführen,
wie wir mit Listen operieren können, wer das benutzen kann.
Also in diesem Spezialfall können wir es tatsächlich eine Zyklenüberwachung einbauen,
im allgemeinen Fall nicht. Das ist, wie gesagt,
das Problem, dann würden wir das Halteproblem der Touring-Maschine lösen. So,
also Fazit deduktive Datenbanken ist, wir berechnen jetzt eine Relation,
statt sie aufzuzählen, wir machen das,
um Redundanz zu vermeiden, indem wir eben nicht Paul,
Anne und Anne Paul aufzählen müssen,
sondern das eine aus dem anderen berechnen können.
Wir sind dadurch in der Lage, Relation über unendlichen Domänen zu spezifizieren,
das haben wir noch nicht gesehen, das kommt aber noch.
Wir können insbesondere auch die transitive Hülle einer Relation berechnen und
wir haben dann aber Terminierungsprobleme möglicherweise zu befürchten und müssen aufpassen,
in welchen Fällen lauern sie und was kann man dagegen tun?
Weil es um persistente Datenhaltung gibt, hätte man natürlich auch ein erhebliches Effizienzproblem,
also diese Berechnung über einer extern gespeicherten Datenbank zu machen,
ist ziemlich aufwendig. Und deshalb ist im SQL 99,
das ist ja aktuell gültiger Standard für SQL,
die Deduktion nur in einem eingeschränkten Modell verfügbar.
Also das ist SQL, Datenbanken sind dadurch nicht zu deduktiven Datenbanken geworden,
aber sie erlauben es in beschränktem Maße,
solche deduktiven Anfragen abzuarbeiten oder rekursive Abfragen abzuarbeiten.
Allerdings ist die Sorge dafür, ob das Ganze terminiert oder
nicht terminiert, die es dem Programmierer überlassen.
Da muss ich also durch geschicktes Setzen von Marken auch nachweisen,
dass ich hier schon mal war, um dann die Weiterverarbeitung abzubrechen.
Gut, das soll es für heute gewesen sein.
Ich dankeschön für die Aufmerksamkeit. Ich wünsche dir ein
schönes Wochenende und tschüss