Dieser Hinweis ist aus der Übung im WS 1994/95 oder aus einer noch älteren Übung oder war nie Teil einer Übung und ist daher möglicherweise für spätere Übungen nicht gültig!
Mengenausdrücke, setof/3 Die Kinder von Maria Theresia konnten wir bisher nur als Lösungsmenge (bzw. Sequenz) darstellen. :- kind_von(Kind, maria_theresia). @ Kind = joseph_II. @ Kind = leopold_II. @ Kind = marie_antoinette. @ 3 Lösungen gefunden Oft möchte man die so gefundenen Lösungen weiterverarbeiten, etwa in Listenform. Die Lösungssequenz muß dazu endlich sein. Das vordefinierte Prädikat setof/3 erlaubt, die Lösungsmenge als ein Ganzes zu betrachten, nicht nur jede Lösung für sich; um etwa die Lösungsmenge als Liste weiterzuverwenden. setof(Lösungsschema, Ziel, Lösungsmenge) Ziel ist z.B. kind_von(Kind, maria_theresia) Lösungsschema ist ein Term, der nur Variablen aus Ziel enthalten sollte, und beschreibt, wie eine Lösung aussehen soll. Etwa hier: Kind. Lösungsmenge ist eine sortierte Liste aller kopierten Instanzen von Lösung, die gefunden wurden. :- setof(Kind, kind_von(Kind, maria_theresia), Kinder). @ Kinder = [joseph_II,leopold_II,marie_antoinette]. @ Eine Lösung gefunden Als Antwort erhalten wir Bindungen für Lösungsmenge und (gelegentlich für Variablen in Ziel, siehe unten), JEDOCH keine Bindungen für Lösungsschema. Lösungsschema dient nur zur Beschreibung eines Element der Lösungsmenge. Diese Anfrage kann verallgemeinert werden, man sieht nun nicht nur die Kinder Maria Theresias. :- setof(Kind, kind_von(Kind, Elternteil), Kinder). @ Elternteil = franz_I, Kinder = [joseph_II,leopold_II]. @ Elternteil = karl_VI, Kinder = [maria_theresia]. @ Elternteil = leopold_I, Kinder = [joseph_I,karl_VI]. @ Elternteil = leopold_II, Kinder = [franz_II]. @ Elternteil = maria_theresia, Kinder = [joseph_II,leopold_II,marie_antoinette]. @ 5 Lösungen gefunden Der obigen Anfrage entspricht: Wer hat welche Kinder? Umgekehrt kann man ebenso fragen: Wer hat welche Eltern? :- setof(Elternteil, kind_von(Kind, Elternteil), Eltern). @ Eltern = [leopold_II], Kind = franz_II. @ Eltern = [leopold_I], Kind = joseph_I. @ Eltern = [franz_I,maria_theresia], Kind = joseph_II. @ Eltern = [leopold_I], Kind = karl_VI. @ Eltern = [franz_I,maria_theresia], Kind = leopold_II. @ 5 Lösungen gefunden Eine ähnliche Anfrage wäre: Welche Kinder? kind(Kind) :- kind_von(Kind, _Elternteil). :- kind(Kind). @ Kind = joseph_I. @ Kind = karl_VI. @ Kind = maria_theresia. @ Kind = joseph_II. @ Kind = joseph_II. % Redundant @ Kind = leopold_II. @ Kind = leopold_II. % Redundant @ Kind = marie_antoinette. @ Kind = franz_II. @ 9 Lösungen gefunden, davon 2 redundant :- setof(Kind, kind(Kind), L). @ L = [franz_II,joseph_I,joseph_II,karl_VI,leopold_II,maria_theresia,marie_antoinette]. @ Eine Lösung gefunden Man sieht in diesem Falle: Die Liste enthält keine Duplikate, die einfache Anfrage aber schon. Bei vielen Anfragen müßte man sich eigens ein Hilfsprädikat wie kind/1 definieren. Denken Sie an die Weltkarte mit ihren zahllosen Argumenten und Kombinationsmöglichkeiten! In der Definition von kind/1 ist _Elternteil eine existentielle Variable. Man kann in einem Ziel derartige Variablen wie folgt explizit existentiell quantifizieren: V1^V2^ZielmitV1undV2 Dadurch ist das Hilfsprädikat nicht mehr nötig. :- setof(Kind, Elternteil^kind_von(Kind, Elternteil), L). @ L = [franz_II,joseph_I,joseph_II,karl_VI,leopold_II,maria_theresia,marie_antoinette]. @ Eine Lösung gefunden Wird Kind existentiell quantifiziert, erhält man die Liste aller Eltern: :- setof(Elternteil, Kind^kind_von(Kind, Elternteil), Eltern). @ Eltern = [franz_I,karl_VI,leopold_I,leopold_II,maria_theresia]. @ Eine Lösung gefunden Und nun eine geschachtelte Verwendung: Die Liste aller Paare Eltern und ihrer Kinder :- setof(Elternteil-Kinder, setof(Kind, kind_von(Kind, Elternteil), Kinder), EKs). @ EKs = [franz_I-[joseph_II,leopold_II],karl_VI-[maria_theresia],leopold_I-[joseph_I,karl_VI],leopold_II-[franz_II],maria_theresia-[joseph_II,leopold_II,marie_antoinette]]. @ Eine Lösung gefunden Hier ist -/2 eine Struktur, sie wird häufig für Paare gebraucht. Man hätte natürlich auch eine x-beliebige andere Struktur verwenden können. :- setof(k(Kind), kind_von(Kind, maria_theresia), Kinder). @ Kinder = [k(joseph_II),k(leopold_II),k(marie_antoinette)]. @ Eine Lösung gefunden Wieviele Kinder Maria Theresias sind bekannt? (Wenn sie überhaupt welche hat) :- setof(Kind, kind_von(Kind, maria_theresia), Kinder), length(Kinder, Kinderzahl). @ Kinder = [joseph_II,leopold_II,marie_antoinette], Kinderzahl = 3. @ Eine Lösung gefunden Gibt es überhaupt keine Lösung, so scheitert jedoch setof/3. Folgene Frage ist also NICHT so direkt möglich bzw. sinnvoll! Wieviele Kinder Marie-Antoinettens sind bekannt? :/- setof(Kind, kind_von(Kind, marie_antoinette), Kinder), length(Kinder, Kinderzahl). Die Antwort ist also nicht 0! :/- kind_von(Kind, marie_antoinette). Man kann dies nun verallgemeinern. anzahl(Lösungsschema, Pred, Zahl) :- setof(Lösungsschema, Pred, Lösungen), length(Lösungen, Zahl). :- anzahl(Kind, kind_von(Kind, Elternteil), Kinderzahl). @ Elternteil = franz_I, Kinderzahl = 2. @ Elternteil = karl_VI, Kinderzahl = 1. @ Elternteil = leopold_I, Kinderzahl = 2. @ Elternteil = leopold_II, Kinderzahl = 1. @ Elternteil = maria_theresia, Kinderzahl = 3. @ 5 Lösungen gefunden Vielleicht ist jetzt auch klar, warum setof/3 scheitert und nicht die leere Liste liefert, wenn das Ziel nicht erfüllt ist. (Erinnern Sie sich an die Negationsgeschichten?) Die folgenden Antworten sollten ja sonst auch gefunden werden. Diesmal nicht nur 27, almwiese, sondern auch sämtliche Päpste. Die untenstehenden Antworten sind also frei erfunden! :- anzahl(Kind, kind_von(Kind, Elternteil), Kinderzahl). @ Elternteil = 27, Kinderzahl = 0. @ Elternteil = almwiese, Kinderzahl = 0. @ Elternteil = donau, Kinderzahl = 0. @ Elternteil = franz_I, Kinderzahl = 2. @ Elternteil = johannes_I, Kinderzahl = 0. @ Elternteil = johannes_II, Kinderzahl = 0. @ Elternteil = johannes_III, Kinderzahl = 0. @ Elternteil = johannes_IV, Kinderzahl = 0. @ Elternteil = johannes_V, Kinderzahl = 0. @ ... @ Elternteil = johannes_XXII, Kinderzahl = 0. @ Elternteil = johannes_XXIII, Kinderzahl = 0. @ Elternteil = karl_VI, Kinderzahl = 1. @ Elternteil = leopold_I, Kinderzahl = 2. @ Elternteil = leopold_II, Kinderzahl = 1. @ Elternteil = marie_antoinette, Kinderzahl = 0. @ Elternteil = maria_theresia, Kinderzahl = 3. @ Elternteil = prolog, Kinderzahl = 0. @ Anfrage unterbrochen, Antwort unvollständig setof/3 kann auch verwendet werden, um redundante Lösungen eines Ziels auszuschließen. Das Lösungsschema interessiert uns hier gar nicht, deshalb das Atom t (oder sonst ein Grundterm). :- setof(t, Elternteil^kind_von(Kind,Elternteil), L). @ Kind = franz_II, L = [t]. @ Kind = joseph_I, L = [t]. @ Kind = joseph_II, L = [t]. @ Kind = karl_VI, L = [t]. @ Kind = leopold_II, L = [t]. @ Kind = maria_theresia, L = [t]. @ Kind = marie_antoinette, L = [t]. @ 7 Lösungen gefunden (Haben Sie das alles bis hierhin gelesen und verstanden? Schaun Sie sich die Weltkarte dazu an! Und: Sie können ja stets Fragen stellen!) \hinweis{PrologAllgemein} Zurück: \hinweis{init}