Für dieses Problem eine explizite Zeit nicht erforderlich ist, so werden wir die Geschichte als eine Liste von Aktionen darstellen. Auf der anderen Seite müssen Sie den Zustand Ihres Systems, d. H. Den aktuellen Inhalt der drei Buckets, explizit darstellen. Der Grund dafür ist, dass Prolog-Datenstrukturen (d. H. Terme) nicht mehr geändert werden können, sobald sie einmal erstellt wurden. Da es viele bedeutungslose Begriffe gibt, ist es eine gute Methode, Datentypen zuerst über ein Prädikat zu definieren. Da Sie zu einem bestimmten Zeitpunkt Arithmetik verwenden (wenn Sie Wasser von einem Eimer in einen anderen gießen), verwende ich arithmetische Einschränkungen anstelle des alten Prädikats is/2
.
:- use_module(library(clpfd)).
Zuerst wir feststellen, dass es 3 Eimer, durch die Atome b1 dargestellt, b2 und b3:
is_bucket(b1).
is_bucket(b2).
is_bucket(b3).
Dann müssen wir unseren Staat definieren. Wir verwenden nur einen Ausdruck buckets/3
, wobei das erste Argument die Kapazität von b1 und ebenso die anderen beiden enthält.
Alle Container dürfen nicht negativ werden, daher setzen wir ihre Domäne auf einen Bereich von Null bis (positiv) unendlich.
Was ist nun eine Aktion? Bisher beschriebene Sie Entleerung und Gießen:
is_action(empty(B)) :-
is_bucket(B).
is_action(pour(From, To)) :-
is_bucket(From),
is_bucket(To).
einen Eimer leeren, wir müssen nur wissen, welche. Wenn wir Wasser von einem zum anderen gießen, müssen wir beides beschreiben. Da wir bereits ein Prädikat haben einen Eimer zu beschreiben, können wir nur eine Regel als „Zustand, wenn From
und To
Eimer sind, dann ist pour(From, To)
eine Aktion.
Jetzt müssen wir erklären, wie eine Aktion einen Zustand verwandelt. Dies ist ein Beziehung zwischen dem alten Zustand, der neue Zustand, und weil wir wissen, gerne würden, was auch die Geschichte. geschieht
% initial state
state_goesto_action(buckets(7,5,3), buckets(7,5,3), []).
der Übergang für den Anfangszustand ändert nichts und hat eine leere Geschichte (die []
).
% state transitions for moving
state_goesto_action(buckets(X,Y,Z), buckets(0,Y,Z), [empty(b1) | History]) :-
state_goesto_action(_S0, buckets(X,Y,Z), History).
kann diese Regel als gelesen werden: „Wenn wir eine Aktion kommt von einem Zustand _S0
führt zu dem Zustand buckets(X,Y,Z)
mit einigen History
hatte, dann können wir die empty(b1)
Aktion als nächstes durchführen und wir werden den Zustand buckets(0,Y,Z)
erreichen“ . Mit anderen Worten, der Status wird aktualisiert und die Aktion wird dem Verlauf vorangestellt. Eine symmetrische Regel funktioniert für die anderen Buckets:
state_goesto_action(buckets(X,Y,Z), buckets(X,0,Z), [empty(b2) | History]) :-
state_goesto_action(_S0, buckets(X,Y,Z), History).
state_goesto_action(buckets(X,Y,Z), buckets(X,Y,0), [empty(b3) | History]) :-
state_goesto_action(_S0, buckets(X,Y,Z), History).
Wie können wir überprüfen, ob dies sinnvoll ist? Lassen Sie uns an Geschichten der Länge aussehen 2:
?- state_goesto_action(_,S1,[H1,H2]).
S1 = buckets(0, 3, 5),
H1 = H2, H2 = empty(b1) .
Ah schön, wenn beide Aktionen empty(b1)
sind, ist der erste Eimer leer und die anderen davon unberührt. Lassen Sie uns an weiteren Lösungen suchen:
S1 = buckets(0, 0, 5),
H1 = empty(b1),
H2 = empty(b2) ;
S1 = buckets(0, 3, 0),
H1 = empty(b1),
H2 = empty(b3) ;
S1 = buckets(0, 0, 5),
H1 = empty(b2),
H2 = empty(b1) ;
S1 = buckets(7, 0, 5),
H1 = H2, H2 = empty(b2) ;
S1 = buckets(7, 0, 0),
H1 = empty(b2),
H2 = empty(b3) ;
S1 = buckets(0, 3, 0),
H1 = empty(b3),
H2 = empty(b1) ;
S1 = buckets(7, 0, 0),
H1 = empty(b3),
H2 = empty(b2) ;
S1 = buckets(7, 3, 0),
H1 = H2, H2 = empty(b3).
Sieht aus wie wir alle Möglichkeiten der Entleerung Eimer (und nichts mehr :-)) erhalten. Jetzt müssen Sie Regeln für das Gießen von einem Eimer zum anderen hinzufügen. Viel Glück!
(Edit: Tippfehler, Fehler in der zweiten Regel)
Zumindest für Prolog macht Ihre Frage keinen Sinn. Versuchen Sie, es in einer Programmiersprache zu formalisieren, um einen Hinweis zu bekommen. – CapelliC
Vielleicht solltest du zuerst erklären, wofür b, t und l stehen und was die Regel machen soll. Angenommen t ist ein Zeitpunkt, b steht für einen Eimer und l ist eine Wassermenge (in Litern). Sie sagen: "Wenn irgendwann ein Eimer leer ist, dann hat jeder Eimer eine beliebige Menge Wasser". Aber dann ist eine Instanz Ihres Axioms: "Zur Zeit t, wenn Eimer b leer ist, enthält Eimer b 100 Liter Wasser." Das ist ein Widerspruch. Da widersprüchliche Axiome alles beweisen, sollten Sie sie nicht verwenden. –
@ CapelliC @ Lambda.xy.x aktualisiert das Problem zum besseren Verständnis. – Mensch