Logické programování Prezentace číslo 6
Logický problém (str.130) Nedělní odpoledne strávily čtyři dvojice na různých místech. Zjistěte, kde a s kým byla Monika, když víte, že: Jiří s Alenou nešli do parku Lucie byla v cukrárně Adam byl v kině Michal nešel s Ivanou a nebyl v cukrárně Karel má narozeniny v září Jedna dvojice šla do divadla
Logický problém (str.130) reseni:- tabulka(T), % vytvoř tabulku napln(T), % naplň tabulku vypis(T). % vypiš tabulku % definice tabulky – 4 řádky („páry“) tabulka(T) :- T = [par(K1,H1,M1), par(K2,H2,M2), par(K3,H3,M3), par(K4,H4,M4)]. vypis([]). vypis([H|T]) :- write(H), nl, vypis(T).
Logický problém (str.130) % vyplnění informací do tabulky napln(T) :- clen(X1,T), kluk(X1,jiri), holka(X1,alena), clen(X2,T), X2 \== X1, misto(X2,park), clen(X3,T), holka(X3,lucie), misto(X3,cukrarna), clen(X4,T), kluk(X4, adam), misto(X4,kino), clen(X5,T), kluk(X5,michal), clen(X6,T), holka(X6,ivana), X5 \== X6, X5 \== X3, clen(X7,T), kluk(X7,karel), clen(X8,T), misto(X8,divadlo), clen(X9,T), holka(X9,monika).
Logický problém (str.130) % pomocné procedury clen(H,[H|_]). clen(X,[_|T]):-clen(X,T). kluk(par(K,_,_),K). % doplň jméno kluka holka(par(_,H,_),H). % doplň jméno holky misto(par(_,_,M),M). % doplň místo ?- reseni. par(jiri,alena,divadlo) par(michal,monika,park) par(karel,lucie,cukrarna) par(adam,ivana,kino)
Predikáty pro řízení průchodu programem Základní predikáty: ! řez fail nikdy nesplněný predikát repeat příkaz cyklu
Použití cyklu Nekonečný cyklus - typická chyba začátečníka nekonecny-cyklus :- repeat, write(pracuji), nl, fail. ?- nekonecny-cyklus. pracuji .... pracuji % pro ukončení stiskněte Ctrl+Break Aborted
Použití cyklu Vstup z klávesnice s kontrolou hodnoty zadej-cislo(N) :- repeat, write('Zadej cislo (1..4)'), read(N), N >= 1, N =< 4, !. ?- zadej-cislo(N). Zadej cislo (1..4)|: 5. % neprojde testem Zadej cislo (1..4)|: 3. N = 3
Použití cyklu Vstup z klávesnice s kontrolou hodnoty (2) zadej-cislo(N) :- repeat, write('Zadej cislo (1..4)'), read(N), N >= 1, N =< 4, integer(N), !. ?- zadej-cislo(N). Zadej cislo (1..4)|: 3.2. % neprojde testem Zadej cislo (1..4)|: 4. N = 4
Použití predikátu fail Nalezení (vypsání) všech řešení zvire(agama). zvire(andulka). … zvire(zralok). vypis-vse:-zvire(X), write(X), nl, fail. vypis-vse:-write('konec vypisu'), nl. % catchall ?- vypis-vse. agama andulka zralok konec vypisu yes
Použití řezu Vynucené zastavení (konstrukce !, fail.) % ruzne(A,B) = totéž jako A\=B ruzne(A,A) :- !, fail. ruzne(_,_). ?- ruzne(3,4). yes ?- ruzne(7,7). no
Použití řezu Vynucené zastavení k ošetření výjimek Každý pták létá. Pštrost je pták a nelétá! ptak(kos). ptak(vrabec). ptak(pstros). .... umi_letat(pstros) :- !, fail. umi_letat(X) :- ptak(X). ?- umi_letat(pstros). ?- umi_letat(kos). no yes ?- umi_letat(X). no
Použití řezu Mnohem lepší řešení (a bez řezu) ptak(kos). ptak(vrabec). ptak(pstros). .... umi_letat(X) :- ptak(X), X\=pstros. ?- umi_letat(pstros). ?- umi_letat(kos). no yes ?- umi_letat(X). X = kos ; X = vrabec ; no
Použití řezu Červený a zelený řez Zelený řez má vliv pouze na efektivnost programu a i po jeho odstranění bude program fungovat korektně. Po odstranění červeného řezu program nebude fungovat správně. % větší ze dvou čísel max(X,Y,X):- X>Y,!. max(X,Y,Y):- Y>=X. ?- max(2,3,X). ?- max(4,2,X). X=3 X=4 yes yes
Použití řezu Červený řez % větší ze dvou čísel podruhé max2(X,Y,X):- X>Y,!. max2(X,Y,Y). % po odstranění řezu nastane problém ?- max2(2,3,X). ?- max2(4,2,X). X=3 X=4; yes X=2 yes
Použití řezu Sjednocení dvou množin (seznamů) % sjednoceni_mnozin(M1,M2,Sjednoceni) sj([],M2,M2). sj([H|T],M2,S) :- clen(H,M2), sj(T,M2,S). sj([H|T],M2,[H|S]) :- not(clen(H,M2)), sj(T,M2,S). % jsou jen dvě možnosti, proč se ptám dvakrát??? sje([],M2,M2). sje([H|T],M2,S):- clen(H,M2), !, sje(T,M2,S). sje([H|T],M2,[H|S]) :- sje(T,M2,S).
Použití řezu Seznamovací kancelář % osoba(Jmeno,Pohlavi,Zajmy]). osoba(karel,m,[golf,film,fotbal,jidlo,tenis,tv,vino]). osoba(tomas,m,[film,fotbal,hokej,jidlo,pivo,tenis,tv]). osoba(alena,z,[bezky,film,hokej,jidlo,tenis,tv,vino]). osoba(zdena,z,[golf,film,hokej,joga,jidlo,tenis,tv]). % seznameni seznameni:- osoba(M,m,Z1), osoba(Z,z,Z2), spol_zajem(Z1,Z2), write(‘Lze seznamit: ‘), write(M), write(‘ ‘), write(Z), nl, fail. seznameni:- write(‘Konec vypisu‘), nl. spol_zajem(Z1,Z2) :- clen(X,Z1), clen(X,Z2), !.