Logické programování Prezentace číslo 7
Třídění Bublinkové třídění % bublinkove-trideni(Sez,Setr-Sez) bubble(S1,S2):-spoj(X,[A,B|T],S1), A > B, !, spoj(X,[B,A|T],Spom), bubble(Spom,S2). bubble(S,S). spoj([],S2,S2). spoj([H|T],S2,[H|W]):- spoj(T,S2,W). ?- bubble([3,5,2,1,6,4],X). X = [1,2,3,4,5,6]
Třídění Quicksort % quicksort(Sez,Setr-Sez) qsort([],[]). qsort([P|T],S):-rozdel(P,T,Me,Ve), qsort(Me,S1), qsort(Ve,S2), spoj(S1,[P|S2],S). %rozdel(Pivot,Sez,Mensi,Vetsi) rozdel(_,[],[],[]). rozdel(P,[H|T],[H|M],V):-H=<P, !, rozdel(P,T,M,V). rozdel(P,[H|T],M,[H|V]):-rozdel(P,T,M,V). ?- qsort([3,5,2,1,6,4],X). X = [1,2,3,5,6,4]
Predikáty pro práci s databází V Prologu je možné za běhu měnit databázi Základní predikáty: asserta(predikát)- vložení do databáze (na začátek) assertz(predikát)- vložení do databáze (na konec) retract(predikát) – odstranění z databáze - v LPA Prologu má marker!!! - pozor na zpětný chod!!! - retract_one(X):-retract(X),!. abolish(predikát/arita) – kompletní odstranění z databáze
Použití predikátů Globální proměnná zvire(pes). ?- pocitadlo. zvire(kocka). zvire(slon). pocitadlo:- asserta(pocet(0)), zvire(X), retract_one(pocet(K)), K1 is K+1, asserta(pocet(K1)), fail. pocitadlo:-retract(pocet(K)), write('Pocet zvirat je:'), write(K), nl. retract_one(X) :- retract(X), !. ?- pocitadlo. Pocet zvirat je:3 yes
Práce s databází Zadání predikátů do databáze zadani:-write('Zadej bludiste'), nl, abolish(dvere/2), repeat, write('Zadej dvere mezi mistnostmi:'), nl, write('Odkud:'), read(O), write('Kam:'), read(K), asserta(dvere(O,K)), write('Pokracovat (a/n):'), getb(X), X=110, !. % read(X),X=n,!. lze(A,B) :- dvere(A,B). lze(A,B) :- dvere(B,A).
Použití predikátů Zadání predikátů do databáze ?- zadani. Zadej bludiste Zadej dvere mezi mistnostmi: Odkud:|: a. Kam:|: b. Pokracovat (a/n): Odkud:|: b. Kam:|: c. yes ?- lze(A,B). A = b , B = c ; A = a , B = b ; A = c , B = a ; no
Cesta v bludišti Hledání cesty metodou do hloubky bludiste:- write('Start:'), read(S), write('Cil:'), read(C), cesta(S,[C]). % cesta(Cil,[Seznam-jiz-navstivenych-mist]) cesta(S,[S|T]) :- write([S|T]), nl, fail. cesta(S,[X|T]) :- lze(X,Y), not(clen(Y,[X|T])), cesta(S,[Y,X|T]). clen(H,[H|_]). clen(X,[_|T]) :- clen(X,T).
Cesta v bludišti ?- zadani. a d b e c f Zadej bludiste .... Pokracovat (a/n): yes ?- bludiste. Start:|: a. Cil:|: f. [a,d,e,b,c,f] [a,b,c,f] [a,b,e,f] [a,d,e,f] no a d b e c f
Cesta v bludišti podruhé Pomocný predikát pro nalezení všech řešení: findall(X,Cíl,Seznam-řešení) nalezne všechny hodnoty proměnné X, pro které je Cíl splněný, a uloží je do seznamu Sez likes(tom,eva). likes(tom,jane). likes(jim,eva). likes(peter,eva). ?- findall(A,likes(A,eva),S). A = _ , S = [tom,jim,peter] ?- findall(B,likes(tom,B),S). B = _ , S = [eva,jane]
Cesta v bludišti podruhé Hledání cesty metodou do šířky bludiste2:- write('Start:'), read(S), write('Cil:'), read(C), cesta(S,[C],[]). % cesta(Cil,[Jedna-cesta],[Dalsi-cesty-ve-fronte]) cesta(S,[S|T],_):-write([S|T]), nl, fail. cesta(S,Cesta,Fronta):- findall(X,nove_cesty(Cesta,X),Sez), spoj(Fronta,Sez,Novy_Sez), Novy_Sez=[H|T], cesta(S,H,T).
Cesta v bludišti podruhé Hledání cesty metodou do šířky % nove-cesty(Cesta,Cesta-o-1-misto-delsi) nove_cesty([H|T],[H1,H|T]):- lze(H,H1), not(clen(H1,[H|T])). clen(H,[H|_]). clen(X,[_|T]) :- clen(X,T). spoj([],S2,S2). spoj([H|T],S2,[H|W]):-spoj(T,S2,W).
Cesta v bludišti podruhé ?- zadani. Zadej bludiste .... Pokracovat (a/n): yes ?- bludiste2. Start:|: a. Cil:|: f. [a,d,e,f] [a,b,e,f] [a,b,c,f] [a,d,e,b,c,f] no a d b e c f
Jak neprogramovat Fibonacciho čísla % 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,… f(0,1). f(1,1). f(K,N) :- K>=1, K1 is K-1, K2 is K-2, f(K1,N1), f(K2,N2), N is N1+N2. ?- f(5,X). X = 8 ?- f(16,X). Error 2, Local Stack Full Aborted
Jak neprogramovat Fibonacciho čísla znovu a lépe % vypocet pres „posouvajici se okno” fb(K,X):-f(0,1,1,K,X). f(K,X,_,K,X) :- !. f(I,F1,F2,K,X) :- I1 is I+1, F3 is F1+F2, f(I1,F2,F3,K,X). ?- fb(16,X). ?- fb(1474,X). X = 1597 X = 8.07763763215647 E307