Stromy, grafy Stromy Uzly stromu Tree jsou reprezentovány termy tree(Left,Value,Right): Left a Right jsou opet stromy, Value je ohodnocení uzlu -í* leaf(Value): Value je ohodnoceni uzlu 6 M Příklad: / \ / \ / \ 2 8 / \ / 14 7 / \ 3 5 tree(tree(leaf(1), 2, tree(leaf(3),4,leaf(5)) ), 6, tree(leaf(7),8,[]) ) Hana Rudová, Logické programování I, 13. května 2011 2 Stromy, grafy Stromy: hledáni prvku in(X,T) Predikát in(X,T) uspeje, pokud se prvek X nachází ve stromu T. Prvek X se nachází ve strome T, jestliže C Xje listem stromu T, jinak leaf(X) & Xje koren stromu T, jinak tree(Left,X,Right) -í* X je menší než koren stromu T, pak se nachází v levém podstromu T, jinak & X se nachází v pravém podstromu T Hana Rudová, Logické programování I, 13. kvetna 2011 3 Stromy, grafy Stromy: hledáni prvku in(X,T) Predikát in(X,T) uspeje, pokud se prvek X nachází ve stromu T. Prvek X se nachází ve strome T, jestliže C Xje listem stromu T, jinak leaf(X) & Xje koren stromu T, jinak tree(Left,X,Right) -í* X je menší než koren stromu T, pak se nachází v levém podstromu T, jinak & X se nachází v pravém podstromu T in(X, leaf(X)) :- 1. in(X, tree(_,X,_)) :- 1. in(X, tree(Left, Root, Right) ) :- XV, pak vznikne nový strom s kořenem V, vpravo má leaf(X) (vlevo je []) pokud T=leaf(V) a X pokud T=tree(L,V,R) a X>V, pak v novém strome L ponechej a X pridej doprava (rekurzivne) pokud T=tree(L,V,R) a XV, pak vznikne nový strom s kořenem V, vpravo má leaf(X) (vlevo je []) pokud T=leaf(V) a X pokud T=tree(L,V,R) a X>V, pak v novém strome L ponechej a X pridej doprava (rekurzivne) pokud T=tree(L,V,R) a XV, 1. add(leaf(V), X, tree(leaf(X),V,[]) ) :- 1. XV, pak vznikne nový strom s kořenem V, vpravo má leaf(X) (vlevo je []) pokud T=leaf(V) a X pokud T=tree(L,V,R) a X>V, pak v novém strome L ponechej a X pridej doprava (rekurzivne) pokud T=tree(L,V,R) a XV, !. add(leaf(V), X, tree(leaf(X),V,[]) ) !. XV, !, add(R,X,R1). add(tree(L,V,R), X, tree(L1,V,R)) X iniciálne jsou argumentu termu volné promenné C- na záver je v N-tém argumentu uložen rodic N-tého uzlu (iniciální uzel oznacíme empty) 1--2 1--2 5--4 5 4 \ | \ | | | | \| \ 6--1--2--3 6--1--2--3 3 3 Uzel=4: rodic(4, 1, 2, empty, 6, 1) Uzel=2: rodic(2,empty,1) Hana Rudová, Logické programování I, 13. kvetna 2011 9 Stromy, grafy Procházení grafu do hloubky: algoritmus I Procházení grafu z uzlu Uzel Vytvoríme term pro rodice (všichni rodici jsou zatím volné promenné) JS> Uzel Uzel má prázdného rodice a má sousedy Sousedi Procházíme (rekurzivne) všechny sousedy v Sousedi dfs(Uzel,Graf,Parents) :- functor(Graf,graf,Pocet), functor(Parents,rodice,Pocet), arg(Uzel,Parents,empty), arg(Uzel,Graf,Sousedi), prochazej_sousedy(Sousedi,Uzel,Graf,Parents). Hana Rudová, Logické programování I, 13. kvetna 2011 10 Stromy, grafy Procházení grafu do hloubky: algoritmus II Procházení sousedů uzlu Uzel (pokud Uzel nemá sousedy, tj. Sousedi=[], koncíme) 1. Uzel Vje první soused 2. Zjistíme rodice uzlu V ... pomocí arg(V,Parents,Rodic) 3. Pokud jsme V ješte neprošli (tedy nemá rodice a platí var(Rodic)), tak (a) nastavíme rodice uzlu V na Uzel ... pomocí arg/3 (b) rekurzivne procházej všechny sousedy uzlu V pokud jsme V prošli, dále tímto uzlem nepokracujeme, tj. celkem (var(Rodic) -> true) 4. Procházej zbývající sousedy uzlu Uzel Hana Rudová, Logické programování I, 13. kvetna 2011 11 Stromy, grafy Procházení grafu do hloubky: algoritmus II Procházení sousedu uzlu Uzel (pokud Uzel nemá sousedy, tj. Sousedi=[], konCíme) 1. Uzel Vje první soused 2. Zjistíme rodice uzlu V ... pomocí arg(V,Parents,Rodic) 3. Pokud jsme V ješte neprošli (tedy nemá rodice a platí var(Rodic)), tak (a) nastavíme rodice uzlu V na Uzel ... pomocí arg/3 (b) rekurzivne procházej všechny sousedy uzlu V pokud jsme V prošli, dále tímto uzlem nepokracujeme, tj. celkem (var(Rodic) -> true) 4. Procházej zbývající sousedy uzlu Uzel prochazej_sousedy([],_,_,_). prochazej_sousedy([V|T],Uzel,Graf,Parents) :- arg(V,Parents,Rodic), ( nonvar(Rodic) -> true ; Rodic = Uzel, arg(V,Graf,SousediV), prochazej_sousedy(SousediV,V,Graf,Parents) ), prochazej_sousedy(T,Uzel,Graf,Parents). Hana Rudová, Logické programování I, 13. kvetna 2011 11 Stromy, grafy DÚ: Procházení grafu do šířky Napište predikát bfs(U,G,P) pro procházení grafu G do šírky z uzlu U. Výsledkem procházení je datová struktura P, která reprezentuje strom vzniklý pri prohledávání grafu G do šírky (pro každý uzel stromu známe jeho rodice). graf([2,3],[1,3],[1,2]). graf([2,4,6],[1,3],[2],[1,5],[4,6],[1,5]). 1--2 \ | \| 3 1-- 2 5- -4 | | 6- -1--2--3 3 U=2: rodic(2,empty,2) 5- - 4 | 6- -1--2-- 3 U=4: rodic(4, 1, 2, empty, 4, 1) Hana Rudová, Logické programování I, 13. kvetna 2011 12 Stromy, grafy