Přiřazování seznamů:
seznam([1, 2, 3]). pikacu1 :- write([1, 2, 3, 4, 5]). pikacu2 :- seznam(X), write(X).
Vzpomeňme na prednášku:
member(H, [H|T]). member(X, [H|T]):-member(X, T).
A ještě jedna trpká vzpomínka:
append([], X, X). append([H|X], Y, [H|Z]) :- append(X, Y, Z).
Vyzkoušejte si v listeneru následující dotazy:
?- append([1,2,3],[4,5,6],LIST). ?- append(L1,L2,[1,2,3,4,5]).
Upovídanější verze predikátu append (funkčně však naprosto shodná):
append2([], X, X) :- write('Zabralo prvni pravidlo'), nl. append2([H|X], Y, [H|Z]) :- write('H je '), write(H), write(' '), write(X), write(Y), write(Z), nl, append2(X, Y, Z), write(X), write(Y), write(Z), nl.
Vyzkoušejte v listeneru následující dotaz:
?- append2([1,2,3],[4,5,6],LIST).
Definice grafu:
hrana(1, 4). hrana(1, 5). hrana(2, 1). hrana(2, 4). hrana(3, 1). hrana(3, 2). hrana(3, 4). hrana(4, 5).
Rekurzivní definice, posloupnost procházených uzlů se ukládá do seznamu:
cesta(X,Y,[X,Y]) :- hrana(X,Y). cesta(X,Y,[X|T]) :- hrana(X,Z), cesta(Z,Y,T).
Použití predikátu FINDALL (v listeneru) a výpis seznamu s X, pro které je splněn predikát cesta(2, 5, X):
?- findall(X, cesta(2, 5, X), LIST_OF_Xs).
Použití predikátu FINDALL (v programu) a výpis seznamu s X, pro které je splněn predikát cesta(2, 5, X):
fa1 :- findall(X, cesta(2, 5, X), LIST_OF_Xs), write(LIST_OF_Xs).
Jiná možnost aneb jak "udělat to samé" jinými prostředky:
fa2 :- cesta(2, 5, X), write(X), nl, fail. fa2.
stáhnout (všiměte si mj. štábní kultury a své programy pište podle tohoto vzoru)
Graf - která místnost je spojena s kterou:
connected(1, 4). connected(1, 5). connected(2, 1). connected(2, 4). connected(3, 1). connected(3, 2). connected(3, 4). connected(4, 5).
Kolikátý pokus o splnění cíle ... při každém neúspěchu plnění "connected" se díky "!" snažíme najít novou unifikaci proměnné X v predikátu "pokus(X)", což je podcíl cíle "go":
pokus(1). pokus(2). pokus(3). pokus(4). pokus(5).
Inicializace. Na začátku programu je Wumpus v místnosti číslo 2:
wumpus(2).
Sledujeme pokusy a pohyb Wumpuse:
go :- pokus(X), write('Pokus cislo '), write(X), nl, movewumpus, nl, write('Skoncil pokus cislo '), write(X).
Nejprve se X unifikuje s číslem místnosti, kde právě Wumpus je. Pak se hledá místnost Y, do které by bylo možno Wumpuse přesunout. Z databáze se vyjme fakt "wumpus(X)" a naopak se do ni přidá fakt "wumpus(Y)".
movewumpus :- wumpus(X), write('Predikat "movewumpus" v akci ... '),nl, write('Pred testem CONNECTED je Wumpus v mistnosti '), write(X),nl, !,connected(X,Y),retract(wumpus(X)), assert(wumpus(Y)), write('Po testu CONNECTED je Wumpus v mistnosti '), write(Y). movewumpus:-write('I do nothing').
Teprve tady bude vidět kouzlo operátoru "!" -> po čtvrtém příkazu "go." se neunifikuje s X v predikátu wumpus(X), ale v predikátu pokus(X) tedy "o uroveň výše". Je to vidět například z toho, že se podruhé nevypisuje hláška 'Predikat "movewumpus" v akci ... '
Pro stále tápající: Zkuste odstranit vykřičník z pravidla "movewumpus" a uvidíte.
Přidáme "wumpus(8).", aby byl vidět další pokus o unifikaci v movewumpus.
wumpus(8).
stáhnout (originální verze)
stáhnout (modifikovaná verze - vypisuje se, kde wumpus je)