-
-
Save jiribenes/ac8c928abea351ccf30efd5f1cbb4f21 to your computer and use it in GitHub Desktop.
Cvičení z Neprocedurálního programování - 1 - Prolog jako databáze faktů
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%% Prolog jako databáze faktů: | |
% Otevřete SWI Prolog a tento soubor. | |
% Tento soubor nahrajte (zkonzultujte) ve SWI Prologu | |
% pomocí příkazu `consult('<cesta k souboru>.pl')`. | |
% Po každé změně napište `make.` pro reloadnutí. | |
%%% Syntaxe Prologu: | |
% :- se čte jako "if"/"pokud" | |
% . se čte jako "end"/"konec" | |
% , se čte jako "and"/"a zároveň" | |
% ; se čte jako "or"/"nebo" | |
%%% Zadání: | |
% Chceme vytvořit systém práv pro kanceláře | |
% Administrátoři | |
admin(jirka). % `jirka` je nějaká konstanta, `admin(Osoba)` je predikát, který platí, pokud je `Osoba` administrátorem. | |
admin(petr). | |
%% Vyzkoušejte ve SWI Prologu dotazy [napište tam tu řádku začínající `?-`, samotný prefix `?-` neopisujte] | |
% ?- admin(jirka). | |
% true. | |
% | |
% ?- admin(pavel). | |
% false. | |
% | |
% ?- admin(X). % `X` je tady proměnná, za kterou se Prolog bude snažit dosazovat | |
% X = jirka ; % tady vám to vypíše jen jeden výsledek, zmáčkněte `;` na klávesnici, aby vám prolog vypsal další | |
% X = petr. | |
% Účetní oddělení | |
uctar(ferda). | |
uctar(ferda2). % kreativní pojmenování další osoby :D | |
% Sami si vyzkoušejte dotazy: `uctar(jirka)`, `uctar(X)`. | |
% Ferda dělá fakt dobrý kafe! | |
dela_dobre_kafe(ferda). | |
% Predikát `smi_do_mistnosti(Osoba, Mistnost)` odpoví true, pokud daná Osoba smí do dané Místnost-i | |
% Admini smí kamkoliv | |
% čteme jako "osoba smí do jakékoliv místnosti, pokud je osoba adminem" | |
smi_do_mistnosti(Osoba, _) :- admin(Osoba). % `_` ignoruje proměnnou (tohle pomůže proti warningům) | |
% Rozmyslete si, že proměnné v klauzuli (před `:-`) jsou obecně kvantifikované (s provšechnítkem!). | |
% Vyzkoušejte dotaz `smi_do_mistnosti(jirka, serverovna)`. | |
% Účtaři smí do účtárny | |
smi_do_mistnosti(Osoba, uctarna) :- uctar(Osoba). | |
% Následující řádka se čte jako | |
% smi_do_mistnosti(Osoba, jidelna_vedle_uctarny) if uctar(Osoba) and dela_dobre_kafe(Osoba) | |
smi_do_mistnosti(Osoba, jidelna_vedle_uctarny) :- uctar(Osoba), dela_dobre_kafe(Osoba). | |
% Všichni smí na záchod a do únikového východu | |
smi_do_mistnosti(Osoba, zachod). | |
smi_do_mistnosti(Osoba, unikovy_vychod). | |
% Vyzkoušejte dotazy: | |
% smi_do_mistnosti(X, uctarna). | |
% smi_do_mistnosti(jirka, X). | |
% smi_do_mistnosti(Osoba, Mistnost). | |
% a rozmyslete si proč vám Prolog odpovídá tak jak odpovídá |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%% Společně jsme psali tohle: | |
% den_po(Den1, Den2): | |
% Den2 je ten den, který je po Den1 | |
den_po(pondeli, utery). | |
den_po(utery, streda). | |
den_po(streda, ctvrtek). | |
den_po(ctvrtek, patek). | |
den_po(patek, sobota). | |
den_po(sobota, nedele). | |
den_po(nedele, pondeli). | |
% den_pred(Den2, Den1) s využitím `den_po`: | |
den_pred(Den2, Den1) :- den_po(Den1, Den2). | |
% Vyzkoušejte dotazy: | |
% den_po(pondeli, X). | |
% den_po(X, Y). | |
% den_po(X, X). | |
% den_pred(X, patek), den_pred(Y, X). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% A ------> B ---> C | |
% \ \ /| | |
% \| \| / | |
% E----------->F | |
% \ /| | |
% \| / | |
% D / | |
% /| / | |
% / / | |
% G ---> H | |
% | |
% Cesty z A do C: | |
% | |
% A, B, C | |
% A, B, F, C | |
% A, E, F, C | |
edge(a, b). | |
edge(a, e). | |
edge(b, c). | |
edge(b, f). | |
%edge(c, a). % Tahle hrana vytvoří cyklus [zkuste odmazat] | |
edge(e, d). | |
edge(e, f). | |
edge(f, c). | |
edge(g, d). | |
edge(g, h). | |
edge(h, f). | |
% Chceme definovat 'path(U, V)', který značí jestli existuje orientovaná cesta z U do V | |
% Hranu z U do V značím jako U -> V | |
% Orientovanou cestu z U do V značím jako U ~~~> V | |
% U -> V | |
path(U, V) :- edge(U, V). | |
% U -> W ~~~> V | |
path(U, V) :- edge(U, W), path(W, V). | |
% Rozmyslete si, že `W` je tady nutně kvantifikovaná _existenčně_ (existítkem) a ne _obecně_ (provšechnítkem). | |
% Vyzkoušejte `path(a, c)`. Mělo by vypsat `true; true; true; false`. | |
% Rozmyslete si proč :) | |
% Dále jsme si v tuto chvíli ukázali `trace.` pro debuggování. [Pomocí `notrace.` zase vypnete!] | |
% Zkuste spustit `trace.` a potom `path(a, c).` | |
% Mačkejte tlačítko `Enter` na klávesnici a koukejte co Prolog dělá :) | |
% Měli byste si tím potvrdit hypotézu, kterou jste si formulovali výše. | |
% Vyzkoušejte si všechny možné způsoby jak zavolat `path`: | |
% `path(a, c)` | |
% `path(X, c)` | |
% `path(a, Y)` | |
% `path(X, Y)` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%%%% Zadání | |
% Vyhodnoťte logickou formuli: | |
% | |
% a(X, Y) ... (X /\ Y) | |
% nebo(X, Y) ... (X \/ Y) | |
% ne(X) ... ~X | |
% | |
% | |
% pla ... T | |
% nepla ... F | |
% Zavolejte `priklad(Z)` ve SWI Prologu | |
% a Prolog vam vypise pravdivost formulky | |
priklad(Z) :- | |
Formulka = a(pla, ne(nebo(nepla, pla))), % T /\ ~(F \/ T) | |
vyhodnot(Formulka, Z). | |
vyhodnot(pla, pla). % pravda se vyhodnotí na pravdu | |
vyhodnot(nepla, nepla). % nepravda se vyhodnotí na nepravdu | |
vyhodnot(ne(X), nepla) :- vyhodnot(X, pla). % negace X je nepravdivá, pokud X je pravdivé | |
vyhodnot(ne(X), pla) :- vyhodnot(X, nepla). % negace X je pravdivá, pokud je X nepravdivé | |
% konjunkce | |
vyhodnot(a(X, Y), Z) :- | |
vyhodnot(X, HX), % nejprve vyhodnotíme levý člen | |
vyhodnot(Y, HY), % ... a pravý člen | |
% máme jen pár možností jak to celé může dopadnout: | |
( (HX=pla, HY=pla, Z=pla) % (T /\ T) = T | |
; (HX=nepla, Z=nepla) % (F /\ _) = F | |
; (HY=nepla, Z=nepla) % (_ /\ F) = F | |
). | |
% disjunkce | |
vyhodnot(nebo(X, Y), Z) :- | |
vyhodnot(X, HX), | |
vyhodnot(Y, HY), | |
( (HX=pla, Z=pla) % (T \/ _) = T | |
; (HY=pla, Z=pla) % (_ \/ T) = T | |
; (HX=nepla, HY=nepla, Z=nepla) % (F \/ F) = F | |
). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment