Aritmetika, seznamy, řez Aritmetika: příklady Jak se liší následující dotazy (na co se kdy ptáme)? Které uspějí (kladná odpověď), které neuspějí (záporná odpověď), a které jsou špatně (dojde k chybě)? Za jakých předpokladů by ty neúspěšné případně špatné uspěly? ■ 1 + 2 =:= 2 + 1 ■ X = Y + 1 ■ X \== Y ■ X is Y + 1 ■ X =\= Y ■ X = Y ■ 1 + 2 =\= 1 - 2 ■ X == Y ■ 1 <= 2 ■ 1+1=2 ■ 1 =< 2 ■ 2 = 1+1 ■ sin(X) is sin(2) ■ 1+1=1+1 ■ sin(X) = sin(2+Y) ■ 1 + 1 is 1 + 1 ■ sin(X) =:= sin(2+Y) Hana Rudová, Logické programování I, 12. března 2007 3 Aritmetika, seznamy, řez Aritmetika Důležitý rozdíl ve vestavěných predikátech i s/2 vs. =/2 vs. =:=/2 ■ i s/2 < konstanta nebo proměnná > is < aritmetický výraz > výraz na pravé straně je nejdříve aritmeticky vyhodnocen a pak unifkován s levou stranou ■ =/2 < libovolný term > = < libovolný term > levá a pravá strana jsou unifikovány ■ "=:="/2 "=\="/2 ">="/2 "=<"/2 < aritmetický výraz > =:= < aritmetický výraz > < aritmetický výraz > =\= < aritmetický výraz > < aritmetický výraz > =< < aritmetický výraz > < aritmetický výraz > >= < aritmetický výraz > levá i pravá strana jsou nejdříve aritmeticky vyhodnoceny a pak porovnány Hana Rudová, Logické programování I, 12. března 2007 2 Aritmetika, seznamy, řez Seznamy a append appendC [], S, S ). appendC [X|S1], S2, [X|S3] ) :- appendC SI, S2, S3). Napište následující predikáty pomocí append/3: ■ TastC X, S ) :- appendC _S1, [X], S). append([3,2] , [6], [3,2,6]). X=6, S=[3,2,6] ■ prefix( SI, S2 ) :- appendC SI, _S3, S2). DÚ: suffix(Sl,S2) ■ member( X, S ) :- appendC SI, [X|S2], S ). appendC[3,4,1], [2,6], [3,4,1,2,6]). X=2, S=[3,4,1,2,6] DÚ: adjacentCX.Y.S) ■ % sublistC+S,+ASB) sublistCS.ASB) :- appendC AS, B, ASB ), appendC A, S, AS ). POZOR na efektivitu, bez append lze často napsat efektivněji Hana Rudová, Logické programování I, 12. března 2007 4 Aritmetika, seznamy, řez Akumulátor a sum_l i st(S, Sum) ?- sum_1ist( [2,3,4], Sum ). bez akumulátoru: sum_list( [], 0 ). sum_list( [H|T], Sum ) :- sum_1ist( T, SumT ), Sum is H + SumT. s akumulátorem: sum_1ist( S, Sum ) :- sum_1ist( S, 0, Sum ). sum_1ist( [], Sum, Sum ). sum_list( [H|T], A, Sum ) :- AI is A + H, sunuli st( T, AI, Sum). Výpočet faktoriálu fact(N,F) s akumulátorem: fact( N, F ) :- fact ( N, 1, F ). fact( 1, F, F ) :- !. fact( N, A, F ) :- N > 1, Al i s N * A, Nl i s N - 1, fact( Nl, Al, F ). Hana Rudová, Logické programování I, 12. března 2007 Aritmetika, seznamy, řez r (X) r (X) r (X) P (X) P (X) P (X) a (X) a (X) b (X) b (X) c (X) c (X) d (X) d (X) -write(rl) . -p(X),write(r2). -write(r3). -write(pl) . -a(X),b(X),!, c(X),d(X),write(p2). -write(p3). -write(al) . -write(a2). - X > 0, write(bl). - X < 0, write(b2). X mod 2 X mod 3 0, write(cl) 0, write(c2) abs(X) < 10, write(dl). write(d2). i Rudová, Logické programování I, 12. března 2007 I ?- X=l,r(X). rl X = 1 ? ; plr2 X = 1 ? ; alblr3 X = 1 ? ; no I ?- X=0,r(X). rl X = 0 ? ; plr2 X = 0 ? ; ala2p3r2 X = 0 ? ; r3 X = 0 ? ; no I ?- X=3,r(X). rl X = 3 ? ; plr2 X = 3 ? ; alblc2dlp2r2 X = 3 ? ; d2p2r2 X = 3 ? ; r3 X = 3 ? ; no I ?- X= -6, rC rl X = -6 ? ; plr2 X = -6 ? ; alb2cldlp2r2 X = -6 ? ; d2p2r2 X = -6 ? ; c2dlp2r2 X = -6 ? ; d2p2r2 X = r3 X = no -6 ? -6 ? Aritmetika, seznamy, Hana Rudová, Logické programování I, 12. března 2007 Aritmetika, seznamy, řez r (X) r (X) r (X) P (X) P (X) P (X) a (X) a (X) b (X) b (X) c (X) c (X) d (X) d (X) -write C rl). -p(X),write(r2) . -write(r3). -write(pl). -a(X),b(X), ! , c(X),d(X),write(p2) . -write(p3). -write(al). -write(a2). - X > 0, write(bl). - X < 0, write(b2). X mod 2 X mod 3 0, write(cl). 0, write(c2). abs(X) < 10, write(dl). write(d2). Prozkoumejte trasy výpočtu a navracet např. pomocí následujících dotazů (vždy : středníkem vyžádejte navracení): (1) X=l,r(X). (3) X=0,r(X). (2) X=3,r(X). (4) X= -6,r(X). Hana Rudová, Logické programování I, 12. března 2007 řez v predikátu p/1 neovlivní alternativ predikátu r/1 dokud nebyl proveden řez, alternativ predikátu a/l se uplatňují, př. neúspěc b/l v dotazu (3) při neúspěchu cíle za řezem se výpočí navrací až k volající proceduře r/1, viz (1 alternativy vzniklé po provedení řezu s zachovávají - další možnosti predikát c/1 viz (2) a (4) Aritmetika, seznamy, řez Řez: maximum Je tato definice predikátu max/3 korektní? max(X,Y,X):-X>=Y,! . max(X,Y,Y). Není, následující dotaz uspěje: ?- max(2 ,1,1). Uveďte dvě možnosti opravy, se zachováním použití řezu a bez. max(X,Y,X):-X>=Y. max(X,Y,Z):-X>=Y,!,Z=X. max(X,Y,Y):-Y>X. max(X,Y,Y). Problém byl v definici, v první verzi se tvrdilo: X=Z a X>=Y => Z=X správná definice je: X>=Y => Z=X Při použití řezu je třeba striktně oddělit vstupní podmínky od výstupních unifikací a výpočtu. Hana Rudová, Logické programování I, 12. března 2007 9 Aritmetika, seznamy, řez Řez: member Jaký je rozdíl mezi následujícími definicemi predikátů member/2. Ve kterých odpovědích se budou lišit? Vyzkoušejte např. pomocí member( X, [1,2,3]). memlCH,[H|_]). memlCH,[_|T]) :- meml(H,T). mem2(H,[H|_]) :- !. mem3(H,[K|_]) :- H==K. mem2(H,[_|T]) :- mem2(H,T). mem3(H,[K|T]) :- H\==K, mem3(H,T). ■ meml/2 vyhledá všechny výskyty, při porovnávání hledaného prvku s prvky seznamu může dojít k vázání proměnných (může sloužit ke generování všech prvků seznamu) ■ mem2/2 najde jenom první výskyt, taky váže proměnné ■ mem3/2 najde jenom první výskyt, proměnné neváže (hledá pouze identické prvky) Dokážete napsat variantu, která hledá jenom identické prvky a přitom najde všechny výskyty? mem4(H,[K|_]) :- H==K. mem4(H,[K.|T]) :- mem4(H,T). Hana Rudová, Logické programování I, 12. března 2007 10 Aritmetika, seznamy, řez Seznamy: i nte rsecti on (A, B, C) DÚ: Napište predikát pro výpočet průniku dvou seznamů. Nápověda: využijte predikát member/2 DÚ: Napište predikát pro výpočtu rozdílu dvou seznamů. Nápověda: využijte predikát member/2 Hana Rudová, Logické programování I, 12. března 2007 Aritmetika, seznamy, řez