Seznamy (pokračování) Optimalizace posledního volání 3 Last Call Optimization (LCO) M Implementační technika snižující nároky na paměť Mnoho vnořených rekurzivních volání je náročné na paměť Použití LCO umožňuje vnořenou rekurzi s konstantními pamětovými nároky M Typický příklad, kdy je možné použití LCO: 3 procedura musí mít pouze jedno rekurzivní volání: v posledním cíli poslední klauzule M cíle předcházející tomuto rekurzivnímu volání musí být deterministické M p( ...):- ... % žádné rekurzivní voláni v těle klauzule p( ...):- ... % žádné rekurzivní voláni v těle klauzule p(...) :- !, p( ... ). % řez zajišťuje determinismus M Tento typ rekurze lze převést na iteraci Hana Rudová, Logické programování 1,11. března 201 3 2 Seznamy LCO a akumulátor M Reformulace rekurzivní procedury, aby umožnila LCO M Výpočet délky seznamu length( Seznam, Délka ) lengthC [] , 0 ). length( [ H | T ], Délka ) :- length( T, Del kaO ), Délka is 1 + DelkaO. Hana Rudová, Logické programování 1,11. března 201 3 3 Seznamy LCO a akumulátor M Reformulace rekurzivní procedury, aby umožnila LCO M Výpočet délky seznamu length( Seznam, Délka ) lengthC [] , 0 ). length( [ H | T ], Délka ) :- length( T, Del kaO ), Délka is 1 + DelkaO. M Upravená procedura, tak aby umožnila LCO: % length( Seznam, ZapocitanaDelka, CelkovaDelka ): % CelkovaDelka = ZapocitanaDelka + ,,počet prvků v Seznam'' Hana Rudová, Logické programování 1,11. března 201 3 3 Seznamy LCO a akumulátor M Reformulace rekurzivní procedury, aby umožnila LCO M Výpočet délky seznamu length( Seznam, Délka ) lengthC [] , 0 ). length( [ H | T ], Délka ) :- length( T, Del kaO ), Délka is 1 + DelkaO. M Upravená procedura, tak aby umožnila LCO: % length( Seznam, ZapocitanaDelka, CelkovaDelka ): length( Seznam, Délka ) :- length( Seznam, 0, Délka ). % pomocný predikát length ( [H | T ] , A, Délka ) :- AO is A + 1, length ( T, AO, Del ka ). M Přídavný argument se nazývá akumulátor CelkovaDelka = ZapocitanaDelka + ,,počet prvků v Seznam length( [] , Délka, Délka ). Hana Rudová, Logické programování 1,11. března 201 3 3 Seznamy max_list s akumulátorem Výpočet největšího prvku v seznamu max_li st (Seznam, Max) max_list([X], X). max_list([X|T], Max) :-max_li st(T,MaxT), ( MaxT >= X, !, Max = MaxT Max = X ). Hana Rudová, Logické programování 1,11. března 201 3 4 Seznamy max_list s akumulátorem Výpočet největšího prvku v seznamu max_li st (Seznam, Max) max_list([X], X). max_list([X|T], Max) :-max_li st(T,MaxT), ( MaxT >= X, !, Max = MaxT Max = X ). max_list([H|T],Max) :- max_li st(T,H,Max). max_list([], Max, Max). max_list([H|T], CastecnyMax, Max) :-C H > CastecnyMax, !, max_list(T, H, Max ) max_list(T, CastecnyMax, Max) ). Hana Rudová, Logické programování 1,11. března 2013 4 Seznamy Akumulátor jako seznam Nalezení seznamu, ve kterém jsou prvky v opačném pořadí reverse( Seznam, OpacnySeznam ) M reverse( [], [] ). reverse( [ H | T ], Opacny ) :- Hana Rudová, Logické programování 1,11. března 201 3 5 Seznamy Akumulátor jako seznam Nalezení seznamu, ve kterém jsou prvky v opačném pořadí reverse( Seznam, OpacnySeznam ) * reverse( [] , [] ). reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). M naivní reverse s kvadratickou složitosti Hana Rudová, Logické programování 1,11. března 201 3 5 Seznamy Akumulátor jako seznam Nalezení seznamu, ve kterém jsou prvky v opačném pořadí reverse( Seznam, OpacnySeznam ) * reverse( [] , [] ). reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). M naivní reverse s kvadratickou složitosti M reverse pomocí akumulátoru s lineární složitostí M % reverse( Seznam, Akumulátor, Opacny ): % Opacny obdržíme přidáním prvků ze Seznam do Akumulátor v opačném poradi Hana Rudová, Logické programování 1,11. března 201 3 5 Seznamy Akumulátor jako seznam Nalezení seznamu, ve kterém jsou prvky v opačném pořadí reverse( Seznam, OpacnySeznam ) * reverse( [] , [] ). reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). M naivní reverse s kvadratickou složitosti M reverse pomocí akumulátoru s lineární složitostí M % reverse( Seznam, Akumulátor, Opacny ): % Opacny obdržíme přidáním prvků ze Seznam do Akumulátor v opačném poradi reverse( Seznam, OpacnySeznam ) :- reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). reverse( [ H | T ], A, Opacny) :- reverse( T, [ H | A ], Opacny ). % přidání H do akumulátoru Hana Rudová, Logické programování 1,11. března 201 3 5 Seznamy Akumulátor jako seznam Nalezení seznamu, ve kterém jsou prvky v opačném pořadí reverse( Seznam, OpacnySeznam ) * reverse( [] , [] ). reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). M naivní reverse s kvadratickou složitosti M reverse pomocí akumulátoru s lineární složitostí M % reverse( Seznam, Akumulátor, Opacny ): % Opacny obdržíme přidáním prvků ze Seznam do Akumulátor v opačném poradi reverse( Seznam, OpacnySeznam ) :- reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). reverse( [ H | T ], A, Opacny) :- reverse( T, [ H | A ], Opacny ). % přidání H do akumulátoru M zpětná konstrukce seznamu (srovnej s předchozí dopřednou konstrukcí, např. append) Hana Rudová, Logické programování 1,11. března 201 3 5 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) — Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) - (1) reverse([l,2,3], [], 0) - Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) - (1) reverse([l,2,3], [], 0) - (3) reverse([2,3] , [1], 0) - Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) - (1) reverse([l,2,3], [], 0) - (3) reverse([2,3] , [1], 0) - (3) reverse([3], [2,1], 0) - Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) - (1) reverse([l,2,3], [], 0) - (3) reverse([2,3] , [1], 0) - (3) reverse([3], [2,1], 0) - (3) reverse([], [3,2,1], 0) - Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy reverse/2: cvičení reverse( Seznam, OpacnySeznam ) :- % (1) reverse( Seznam, [], OpacnySeznam). reverse( [], S, S ). % (2) reverse( [H | T ], A, Opacny ) :- % (3) reverse( T, [ H | A ], Opacny ). ? - reverse([l,2,3],0). reverse([l,2,3],0) - (1) reverse([l,2,3], [], 0) - (3) reverse([2,3] , [1], 0) - (3) reverse([3], [2,1], 0) - (3) reverse([], [3,2,1], 0) - (2) yes 0=[3,2,1] Hana Rudová, Logické programování 1,11. března 201 3 6 Seznamy Neefektivita při spojování seznamů M Sjednocení dvou seznamů M append( [], S, S ). append( [X|S1], S2, [X|S3] ) :- append( SI, S2, S3 ). Hana Rudová, Logické programování 1,11. března 201 3 7 Neefektivita při spojování seznamů M Sjednocení dvou seznamů M append( [], S, S ). append( [X|S1], S2, [X|S3] ) :- append( SI, S2, S3 ). ?- append( [2,3], [1], S ). Hana Rudová, Logické programování 1,11. března 201 3 7 Seznamy Neefektivita při spojování seznamů Sjednocení dvou seznamů 3 append( [], S, S ). append( [X|S1], S2, [X|S3] ) :- append( SI, S2, S3 ). 3 ?- append( [2,3], [1], S ). postupné volání cílů: append( [2,3], [1L S ) - append( [3], [1 ], S') - append( [], [1 ], S" ) Hana Rudová, Logické programování 1,11. března 201 3 7 Seznamy Neefektivita při spojování seznamů Sjednocení dvou seznamů M append( [], S, S ). append( [X|S1], S2, [X|S3] ) :- append( SI, S2, S3 ). 3 ?- append( [2,3], [1], S ). postupné volání cílů: append( [2,3], [1], S ) - append( [3], [1], S') - append( [], [1], S" ) M Vždy je nutné projít celý první seznam Hana Rudová, Logické programování 1,11. března 201 3 7 Seznamy Rozdílové seznamy Zapamatování konce a připojení na konec: rozdílové seznamy Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy Rozdílové seznamy Zapamatování konce a připojení na konec: rozdílové seznamy * [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy Rozdílové seznamy Zapamatování konce a připojení na konec: rozdílové seznamy [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L A1 Z1 A2 Z2 v v l L1 L2 \ ^-^ L3 append( Al-Zl, Z1-Z2, A1-Z2 ) LI L2 L3 Hana Rudová, Logické programování 1,11. března 201 3 8 Rozdílové seznamy Zapamatování konce a připojení na konec: rozdílové seznamy [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L A1 Z1 A2 Z2 v v l L1 L2 \ ^-^ L3 append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy seznamy Zapamatování konce a připojení na konec: rozdílové seznamy [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L A1 Z1 A2 Z2 v v l L1 L2 \ ^-^ L3 append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 ?- append( [2,3|Z1]-Z1, [1|Z2]-Z2, S ). S = Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy seznamy Zapamatování konce a připojení na konec: rozdílové seznamy [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L A1 Z1 A2 Z2 v v l L1 L2 \ ^-^ L3 append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 ?- append( [2,3|Z1]-Z1, [1|Z2]-Z2, S ). S = AI - Z2 = Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy seznamy Zapamatování konce a připojení na konec: rozdílové seznamy [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L A1 Z1 A2 Z2 v v l L1 L2 \ ^-^ L3 append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 ?- append( [2,3|Z1]-Z1, [1|Z2]-Z2, S ). S = AI - Z2 = [2,3|Z1] - Z2 = Hana Rudová, Logické programování 1,11. března 201 3 8 Seznamy Kozaiiove seznamy Zapamatování konce a připojení na konec: rozdílové seznamy M [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 ^ ?- append( [2,3|Z1]-Z1, [1|Z2]-Z2, S ). S = AI - Z2 = [2,3|Zl] - Z2 = [2,3| [1|Z2] ] - Z2 A1 Z1 A2 MM Z2 L1 L2 L3 Hana Rudová, Logické programování I, 11. března 201 3 8 Seznamy Kozaiiove seznamy Zapamatování konce a připojení na konec: rozdílové seznamy M [a,b] = L1-L2 = [a,b|T]-T = [a,b,c|S]-[c|S] = [a,b,c]-[c] Reprezentace prázdného seznamu: L-L append( Al-Zl, Z1-Z2, A1-Z2 ). LI L2 L3 [2,3] [1] [2,3,1] [2,3|Z1]-Z1 [1|Z2]-Z2 [2,3,1|Z2]-Z2 ^ ?- append( [2,3|Z1]-Z1, [1|Z2]-Z2, S ). S = AI - Z2 = [2,3|Zl] - Z2 = [2,3| [1|Z2] ] - Z2 Zl = [1|Z2] S = [2,3,1|Z2]-Z2 M Jednotková složitost, oblíbená technika ale není tak flexibilní A1 Z1 A2 MM Z2 L1 L2 L3 Hana Rudová, Logické programování I, 11. března 201 3 8 Seznamy Akumulátor vs. rozdílové seznamy: reverse reverse( [] , [] ) . reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). kvadratická složitost reverse( Seznam, Opacny ) :- reverseO( Seznam, [], Opacny ). reverseO( [], S, S ). reverseO( [ H | T ], A, Opacny ) :- reverseO( T, [H I A ], Opacny ). akumulátor (lineárni) Hana Rudová, Logické programování 1,11. března 201 3 9 Seznamy Akumulátor vs. rozdílové seznamy: reverse reverse( [] , [] ) . reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). kvadratická složitost reverse( Seznam, Opacny ) :- reverseO( Seznam, [], Opacny ). reverseO( [], S, S ). reverseO( [ H | T ], A, Opacny ) :- reverseO( T, [ H | A ], Opacny ). akumulátor (lineárni) reverse( Seznam, Opacny ) :- reverseO( Seznam, Opacny-[]). reverseO( [], S-S ). reverseO( [ H | T ], Opacny-OpacnyKonec ) :- rozdilové seznamy reverseO( T, Opacny-[ H | OpacnyKonec] ). (lineárni) Hana Rudová, Logické programování 1,11. března 201 3 9 Seznamy Akumulátor vs. rozdílové seznamy: reverse reverse( [] , [] ) . reverse( [ H | T ], Opacny ) :-reverse( T, OpacnyT ), append( OpacnyT, [ H ], Opacny ). kvadratická složitost reverse( Seznam, Opacny ) :- reverseO( Seznam, [], Opacny ). reverseO( [], S, S ). reverseO( [ H | T ], A, Opacny ) :- reverseO( T, [ H | A ], Opacny ). akumulátor (lineárni) reverse( Seznam, Opacny ) :- reverseO( Seznam, Opacny-[]). reverseO( [], S-S ). reverseO( [ H | T ], Opacny-OpacnyKonec ) :- rozdilové seznamy reverseO( T, Opacny-[ H | OpacnyKonec] ). (lineárni) Příklad: operace pro manipulaci s frontou 3 test na prázdnost, přidání na konec, odebrání ze začátku Hana Rudová, Logické programování 1,11. března 201 3 9 Seznamy Vestavěné predikáty Vestavěné predikáty Predikáty pro řízení běhu programu M fai 1 , true, ... M Různé typy rovností 3 unifikace, aritmetická rovnost, ... M Databázové operace 3 změna programu (programové databáze) za jeho běhu M Vstup a výstup M Všechna řešení programu M Testování typu termu 3 proměnná?, konstanta?, struktura?, ... M Konstrukce a dekompozice termu M argumenty?, funktor?, ... Hana Rudová, Logické programování 1,11. března 2013 11 Vestavěné predikáty Databázové operace Databáze: specifikace množiny relací Prologovský program: programová databáze, kde jsou relace specifikovány explicitně (fakty) i implicitně (pravidly) Vestavěné predikáty pro změnu databáze během provádění programu: assert( Klauzule ) přidání Klauzule do programu asserta( Klauzule ) přidání na začátek assertz( Klauzule ) přidání na konec retract( Klauzule ) smazání klauzule unifikovatelné s Klauzule Pozor: nadměrné použití těchto operací snižuje srozumitelnost programu Hana Rudová, Logické programování 1,11. března 201 3 12 Vestavěné predikáty Příklad: databázové operace M Caching. odpovědi na dotazy jsou přidány do programové databáze Hana Rudová, Logické programování 1,11. března 201 3 Vestavěné predikáty Příklad: databázové operace Caching: odpovědi na dotazy jsou přidány do programové databáze M ?- solve( problem, Solution), asserta( solve( problem, Solution) ). 3 :- dynamic solve/2. % nezbytné při použití v SICStus Prologu Rudová, Logické programování 1,11. března 201 3 Vestavěné predikáty Příklad: databázové operace M Caching, odpovědi na dotazy jsou přidány do programové databáze M ?- solve( problem, Solution), asserta( solve( problem, Solution) ). 3 :- dynamic solve/2. % nezbytné při použití v SICStus Prologu 3 Příklad: uloz_trojice( Seznámí, Seznam2 ) :-member( XI, Seznámí ), member( X2, Seznam2 ), spocitej_treti( XI, X2, X3 ), assertz( trojice( XI, X2, X3 ) ), f ai 1 . Hana Rudová, Logické programování 1,11. března 2013 13 Vestavěné predikáty Příklad: databázové operace M Caching, odpovědi na dotazy jsou přidány do programové databáze M ?- solve( problem, Solution), asserta( solve( problem, Solution) ). 3 :- dynamic solve/2. % nezbytné při použití v SICStus Prologu 3 Příklad: uloz_trojice( Seznámí, Seznam2 ) :-member( XI, Seznámí ), member( X2, Seznam2 ), spocitej_treti( XI, X2, X3 ), assertz( trojice( XI, X2, X3 ) ), f ai 1 . uloz_trojice( _, _ ) :- !. Hana Rudová, Logické programování 1,11. března 2013 13 Vestavěné predikáty Vstup a výstup program může číst data ze vstupního proudu (input stream) program může zapisovat data do výstupního proudu (output stream) dva aktivní proudy M aktivní vstupní proud 3 aktivní výstupní proud uživatelský terminál - user 3 datový vstup z terminálu user chápán jako jeden ze vstupních proudů datový výstup na terminál chápán jako jeden z výstupních proudů soubor 1 soubor 2 uživatelsky terminal program user soubor 3 soubor 4 vstupni proudy vystupni proudy Hana Rudová, Logické programování I, 11. března 201 3 14 Vestavěné predikáty Vstupní a výstupní proudy: vestavěné predikáty M změna (otevření) aktivního vstupního/výstupního proudu: see(S)/tell (S) ctěni( Soubor ) :- see( Soubor ), cteni_ze_souboru( Informace ), see( user ). uzavření aktivního vstupního/výstupního proudu: seen/told Hana Rudová, Logické programování 1,11. března 201 3 Vestavěné predikáty Vstupní a výstupní proudy: vestavěné predikáty M změna (otevření) aktivního vstupního/výstupního proudu: see(S)/tell (S) ctěni( Soubor ) :- see( Soubor ), cteni_ze_souboru( Informace ), see( user ). uzavření aktivního vstupního/výstupního proudu: seen/told M zjištění aktivního vstupního/výstupního proudu: seeing(S)/tel 1 ing(S) ctěni( Soubor ) :- seeing( StarySoubor ), see( Soubor ), cteni_ze_souboru( Informace ), seen, see( StarySoubor ). Hana Rudová, Logické programování 1,11. března 201 3 Vestavěné predikáty Sekvenční přístup čtení dalšího termu: read(Term) M při čtení jsou termy odděleny tečkou | ?- read(A), read( ahoj(B) ), k textovým souborům read( [C,D] ). Hana Rudová, Logické programování 1,11. března 201 3 16 Vestavěné predikáty Sekvenční přístup k textovým souborům čtení dalšího termu: read(Term) M při čtení jsou termy odděleny tečkou | ?- read(A), read( ahoj(B) ), read( [C,D] ). |: ahoj. ahoj( petre ). [ ahoj( 'Petre!' ), jdeme ]. A = ahoj, B = petre, C = ahoj('Petre!'), D = jdeme Hana Rudová, Logické programování 1,11. března 201 3 16 Vestavěné predikáty Sekvenční přístup k textovým souborům M čtení dalšího termu: read(Term) M při čtení jsou termy odděleny tečkou | ?- read(A), read( ahoj(B) ), read( [C,D] ). |: ahoj. ahoj( petre ). [ ahoj( 'Petre!' ), jdeme ]. A = ahoj, B = petre, C = ahoj('Petre!'), D = jdeme * po dosažení konce souboru je vrácen atom end_of_fi 1 e zápis dalšího termu: write(Term) ?- write( ahoj ). ?- write( 'Ahoj Petre!' ). nový řádek na výstup: nl N mezer na výstup: tab(N) Hana Rudová, Logické programování 1,11. března 201 3 16 Vestavěné predikáty Sekvenční přístup k textovým souborům M čtení dalšího termu: read(Term) 3 při čtení jsou termy odděleny tečkou | ?- read(A), read( ahoj(B) ), read( [C,D] ). |: ahoj. ahoj( petre ). [ ahoj( 'Petre!' ), jdeme ]. A = ahoj, B = petre, C = ahoj('Petre!'), D = jdeme 3 po dosažení konce souboru je vrácen atom end_of_fi 1 e zápis dalšího termu: write(Term) ?- write( ahoj ). ?- write( 'Ahoj Petre!' ). nový řádek na výstup: nl N mezer na výstup: tab(N) čtení/zápis dalšího znaku: getO(Znak) , get(NeprazdnyZnak)/put(Znak) 3 po dosažení konce souboru je vrácena -1 Hana Rudová, Logické programování 1,11. března 2013 16 Vestavěné predikáty Příklad čtení ze souboru process_file( Soubor ) :- seeing( StarySoubor ), see( Soubor ), repeat, read( Term ), process_term( Term ), Term == end_of_file, i ■ » seen, see( StarySoubor ). repeat. repeat :- repeat. 6 zjištěni aktivniho proudu vo otevřeni souboru Soubor vo čteni termu Term vo manipulace s termem vo je konec souboru? vo uzavřeni souboru 6 aktivace původniho proudu 6 opakováni Hana Rudová, Logické programování 1,11. března 201 3 Vestavěné predikáty Ctení programu ze souboru Interpretování kódu programu ?- consul t(program) . ?- consultCprogram.pl') . 3 ?- consult( [programl, 'program2.pl'] ). M Kompilace kódu programu ?- compile( [programl, 'program2.pl'] ). M ?- [program]. 3 ?- [user]. zadávání kódu ze vstupu ukončené CTRL+D M další varianty podobně jako u interpretování 3 typické zrychlení: 5 až 10 krát Hana Rudová, Logické programování 1,11. března 201 3 18 Vestavěné predikáty Všechna řešení Backtracking vrací pouze jedno řešení po druhém M Všechna řešení dostupná najednou: bagof/3, setof/3, findall/3 M bagof( X, P, S ): vrátí seznam S, všech objektů X takových, že P je splněno vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, vek( Dite, 5 ), Seznam ). Hana Rudová, Logické programování 1,11. března 201 3 19 Vestavěné predikáty Všechna řešení Backtracking vrací pouze jedno řešení po druhém M Všechna řešení dostupná najednou: bagof/3, setof/3, findall/3 M bagof( X, P, S ): vrátí seznam S, všech objektů X takových, že P je splněno vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, vek( Dite, 5 ), Seznam ). Seznam = [ anna, tomas ] Hana Rudová, Logické programování 1,11. března 201 3 19 Vestavěné predikáty Všechna řešení Backtracking vrací pouze jedno řešení po druhém M Všechna řešení dostupná najednou: bagof/3, setof/3, findall/3 M bagof( X, P, S ): vrátí seznam S, všech objektů X takových, že P je splněno vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, vek( Dite, 5 ), Seznam ). Seznam = [ anna, tomas ] M Volné proměnné v cíli P jsou všeobecně kvantifikovány ?- bagof( Dite, vek( Dite, Vek ), Seznam ). Hana Rudová, Logické programování 1,11. března 201 3 19 Vestavěné predikáty Všechna řešení Backtracking vrací pouze jedno řešení po druhém M Všechna řešení dostupná najednou: bagof/3, setof/3, findall/3 M bagof( X, P, S ): vrátí seznam S, všech objektů X takových, že P je splněno vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, vek( Dite, 5 ), Seznam ). Seznam = [ anna, tomas ] M Volné proměnné v cíli P jsou všeobecně kvantifikovány ?- bagof( Dite, vek( Dite, Vek ), Seznam ). Vek = 7, Seznam = [ petr ]; Vek = 5, Seznam = [ anna, tomas ] Hana Rudová, Logické programování 1,11. března 201 3 19 Vestavěné predikáty Všechna řešení II Pokud neexistuje řešení bagof(X, P,S) neuspěje 3 bagof: pokud nějaké řešení existuje několikrát, pak S obsahuje duplicity M bagof, setof, findall: P je libovolný cíl vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, ( vek( Dite, 5 ), Dite \= anna ), Seznam ). Seznam = [ tomas ] Hana Rudová, Logické programování 1,11. března 201 3 20 Vestavěné predikáty Všechna řešení II Pokud neexistuje řešení bagof(X, P,S) neuspěje 3 bagof: pokud nějaké řešení existuje několikrát, pak S obsahuje duplicity bagof, setof, findall: P je libovolný cíl vek( petr, 7 ). vek( anna, 5 ). vek( tomas, 5 ). ?- bagof( Dite, ( vek( Dite, 5 ), Dite \= anna ), Seznam ). Seznam = [ tomas ] bagof, setof, findall: na objekty shromažďované v X nejsou žádná omezení: X je term ?- bagof( Dite-Vek, vek( Dite, Vek ), Seznam ). Seznam = [petr-7,anna-5,tomas-5] Hana Rudová, Logické programování 1,11. března 201 3 20 Vestavěné predikáty Existenční kvantifikátor „" " Přidání existenčního kvantifikátoru „~ " ^> hodnota proměnné nemá význam ?- bagof( Dite, Vek~vek( Dite, Vek ), Seznam ). Rudová, Logické programování 1,11. března 201 3 21 Vestavěné predikáty Existenční kvantifikátor „" " Přidání existenčního kvantifikátoru „~ " => hodnota proměnné nemá význam ?- bagof( Dite, Vek~vek( Dite, Vek ), Seznam ). Seznam = [petr,anna,tomas] Rudová, Logické programování 1,11. března 201 3 21 Vestavěné predikáty Existenční kvantifikátor „" " M Přidání existenčního kvantifikátoru „~ " ^> hodnota proměnné nemá význam ?- bagof( Dite, Vek~vek( Dite, Vek ), Seznam ). Seznam = [petr,anna,tomas] Anonymní proměnné jsou všeobecně kvantifikovány, i když jejich hodnota není (jako vždy) vracena na výstup ?- bagof( Dite, vek( Dite, _Vek ), Seznam ). Seznam = [petr] ; Seznam = [anna,tomas] Hana Rudová, Logické programování 1,11. března 201 3 21 Vestavěné predikáty Existenční kvantifikátor „" " M Přidání existenčního kvantifikátoru „~ " ^> hodnota proměnné nemá význam ?- bagof( Dite, Vek~vek( Dite, Vek ), Seznam ). Seznam = [petr,anna,tomas] Anonymní proměnné jsou všeobecně kvantifikovány, i když jejich hodnota není (jako vždy) vracena na výstup ?- bagof( Dite, vek( Dite, _Vek ), Seznam ). Seznam = [petr] ; Seznam = [anna,tomas] Před operátorem „" " může být i seznam ?- bagof( Vek ,[Jméno,Prijmeni]"vek( Jméno, Prijmeni, Vek ), Seznam ). Seznam = [7,5,5] Hana Rudová, Logické programování 1,11. března 201 3 21 Vestavěné predikáty Všechna řešení III. setof( X, P, S ): rozdíly od bagof S je uspořádaný podle @< 3 případné duplicity v S jsou eliminovány Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty Všechna řešení III. 3 setof( X, P, S ): rozdíly od bagof M S je uspořádaný podle @< M případné duplicity v S jsou eliminovány findall( X, P, S ): rozdíly od bagof M všechny proměnné jsou existenčně kvantifikovány ?- findaIK Dite, vek( Dite, Vek ), Seznam ). Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty Všechna řešení III «• setof( X, P, S ): rozdíly od bagof & S je uspořádaný podle @< 3 případné duplicity v S jsou eliminovány findall( X, P, S ): rozdíly od bagof M všechny proměnné jsou existenčně kvantifikovány ?- findall( Dite, vek( Dite, Vek ), Seznam ). ^ vS jsou shromažďovány všechny možnosti i pro různá řešení => findall uspěje přesně jednou Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty Všechna řešení M setof( X, P, S ): rozdíly od bagof 3 S je uspořádaný podle @< 3 případné duplicity v S jsou eliminovány M findallC X, P, S ): rozdíly od bagof 3 všechny proměnné jsou existenčně kvantifikovány ?- findaIK Dite, vek( Dite, Vek ), Seznam ). ^> v S jsou shromažďovány všechny možnosti i pro různá řešení => findall uspěje přesně jednou 3 výsledný seznam může být prázdný => pokud neexistuje řešení, uspěje a vrátí S = [] Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty Všechna řešení M setof( X, P, S ): rozdíly od bagof * S je uspořádaný podle @< 3 případné duplicity v S jsou eliminovány M findall( X, P, S ): rozdíly od bagof 3 všechny proměnné jsou existenčně kvantifikovány ?- findall( Dite, vek( Dite, Vek ), Seznam ). ^> v S jsou shromažďovány všechny možnosti i pro různá řešení => findall uspěje přesně jednou 3 výsledný seznam může být prázdný => pokud neexistuje řešení, uspěje a vrátí S = [] M ?- bagof( Dite, vek( Dite, Vek ), Seznam ). Vek = 7, Seznam = [ petr ]; Vek = 5, Seznam = [ anna, tomas ] ?- findall( Dite, vek( Dite, Vek ), Seznam ). Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty Všechna řešení M setof( X, P, S ): rozdíly od bagof 3 S je uspořádaný podle @< 3 případné duplicity v S jsou eliminovány M findall( X, P, S ): rozdíly od bagof 3 všechny proměnné jsou existenčně kvantifikovány ?- findall( Dite, vek( Dite, Vek ), Seznam ). ^> v S jsou shromažďovány všechny možnosti i pro různá řešení => findall uspěje přesně jednou 3 výsledný seznam může být prázdný => pokud neexistuje řešení, uspěje a vrátí S = [] 3 ?- bagof( Dite, vek( Dite, Vek ), Seznam ). Vek = 7, Seznam = [ petr ]; Vek = 5, Seznam = [ anna, tomas ] ?- findall( Dite, vek( Dite, Vek ), Seznam ). Seznam = [petr,anna,tomas] Hana Rudová, Logické programování 1,11. března 201 3 22 Vestavěné predikáty