120 likes | 248 Views
Ladění, pred. vyšších řádů (7). Jan Hric, KTI MFF UK,1997-2010a http://kti.ms.mff.cuni.cz/~hric. Ladění. Krabičkový model 4 brány: Call: první zavolání cíle Exit: úspěšné ukončení cíle Redo: návrat do cíle, hledání alternativ Fail: celkový neúspěch vstupní brány: Call, Redo
E N D
Ladění, pred. vyšších řádů (7) Jan Hric, KTI MFF UK,1997-2010a http://kti.ms.mff.cuni.cz/~hric
Ladění • Krabičkový model • 4 brány: • Call: první zavolání cíle • Exit: úspěšné ukončení cíle • Redo: návrat do cíle, hledání alternativ • Fail: celkový neúspěch • vstupní brány: Call, Redo • výstupní: Exit, Fail
Ladění II - predikáty • trasování (taky v menu): • trace/0 zapne • notrace/0 vypne • spypointy: • spy(P/N) nastaví spypoint • nospy(P/N) zruší -”- • ladění pomocí spypointů (i v menu) • debug/0 zapne ladění • nodebug/0 vypne ladění • debugging/0 vypíše nastavení
Práce s množinami řešení • převod reprezentací: backtracking na seznam řešení • setof(Term, Cil, Seznam) • Pro každou nalezenou substituci S, která splňuje Cil, se d.s. S(Term) přidá do Seznamu • najde všechny hodnoty Termu (s aplikovanou subs. S), které splňují Cil • vráti jejich Seznam, uspořádaný, bez duplicit • Seznam je vždy neprázdný, při prázdném výsl. seznamu setof/3 neuspěje • backtrackuje přes volné proměnné v Cíli • Cíl tvaru V1^V2^...^C (pouze zde: setof, bagof) • V1,V2,... jsou existenčne kvantifikované, • na jejich hodnotách nezáleží, nebacktrackuje sa přes ně • Cíl může být složený (v závorkách) • bagof/3 • analogicky, vrací neuspořádanou multimnožinu řešení (bag) • findall/3 • Všechny proměnné jsou existenčně kvantifikované, uspěje jednou
setof – příklady chování ?- setof(R, D^rodic(R,D), L). % existenční proměnná D L=[adam,anna,bohus,bozena] ; no ?- setof(R, rodic(R,D), L). % backtracking pro různé hodn. D L=[adam,anna] ; %{D=bohus} L=[adam,anna] ; %{D=bara} L=[bohus,bozena] ; %{D=cyril} no ?- setof(M+O, D^(rodic(M,D),rodic(O,D),M\=O),L). % struktura L=[adam+anna,anna+adam,bohus+bozena,bozena+bohus] ; no ?- bagof(R, D^rodic(R,D), L). % bag L=[adam,anna,adam,anna,bohus,bozena] ; no rodic(anna,bohus). % jeden fakt procedury rodic/2 rodic(adam,bohus). % význam: Adam je rodicem Bohuse rodic(anna,bara). rodic(adam,bara). rodic(bohus,cyril). rodic(bozena,cyril).
Příklad - setof • reprezentace grafů: graf([V-OV],[h(V1,V2,OH)] • interface: vrchol/3, hrana/4 vrchol(graf(Vs,_Hs),V,OV) :-member(V-OV,Vs). hrana(graf(_Vs,Hs),V1,V2,OH):-member(h(V1,V2,OH),Hs). • druhá reprezentace: [V1-OV-[V2-OH]] prevod(G1,G2):- setof(V1-OV-Vs, (vrchol(G1,V1,OV),setof(V2-OH,hrana(G1,V1,V2,OH),Vs)), G2). • DC: dopracujte, aby G2 obsahoval i izolované vrcholy • Použití existenčne kvantifikovaných proměnných: sousede(G1,V,S):-setof(V2,OV^hrana(G1,V,V2,OV),S). • Pro setof(V2,hrana(G1,V,V2,_),S) backtrackuje přes různé hodnoty ohodnocení a teda vrací nevhodné výsledky
Metoda “generuj a testuj” • použití: prohledávací úlohy, využijeme prologovské prohledávání (do hloubky) • př.: obarvení grafu n barvami, tvorba krížovky, kombinatorické problémy ... • posbírat rozumná řešení pomocí setof • musí být “málo řešení” • NP-úplné problémy lehko popíšete, ale … batoh(Bs,S,Os):- % najít podmnožinu Bs, že její součet je S subset(Os,Bs), suma(Os,S). • problém: obvykle neefektivní postup • generovat po částech a hned testovat, co se dá
Převod termu na cíl: call/1 • call/1 převede term v argumentu na cíl a zavolá ho • akceptuje i složené cíle • jméno volaného predikátu musí být známé • proměnné na místě predikátů: převod: X --> call(X) • cíl lze zkonstrovat za běhu (ze známých pred.) => „late binding“, „hooks“ • př.: not, \+, setof, … • not(X):-call(X),!,fail;true. • př.: sekvence(P,Q):- call(P),call(Q). • př.: sekvence2(P,Q):- call((P,Q)). • argumenty se přidají pomocí =.. • problémy s přejmenováním proměnných • => používat jen na termy bez proměnných (zatím) • Mimo standard: call/n, přidá další argumenty a zavolá • Př.: call(append([X]),I,O) , jako append([X],I,O) • Nepřejmenuje proměnné ve volaném cíli -> ručně: copy_term(Term,T0)
Programování vyšších řádů • predikáty (jména p.) jako vstupní parametry, (tj. pointry na p.) • znovupoužitelnost kódu, vyšší abstrakce • parametrické spracování seznamu: map(Pred, In, Out) • Pred/2 se zavolá na každý prvek In a vrátí prvek Out • př.: první, poslední sloupec matice map(_P,[],[]). map( P,[I|Is],[O|Os]):- mycall(P,[I,O]),map(P,Is,Os). % nebo: call(P,I,O) posledni_sloupec(M,S):-map(last,M,S). last(L,Last):-append(_,[Last],L). • argumenty se přidají pomocí =.. ,anebo použít call/n, n>1 (SWI) mycall(P,Args):- C=..[P|Args], call(C). • P je 1 jméno predikátu (ne složený cíl), • Volané cíle jsou pojmenované predikáty v db. • idea map je použitelná na libovolnou d.s., na víc args. • Procedurální parametry: už jsme použili: foreach • DC: akumuluj/3, prvky seznamu jsou data, ale i „příkazy“
(Částečná spec. argumentů) • predikát má několik prvních arg. daných, zbylé jsou parametry map_matice(P,I,O):- map(map(P),I,O). % matice jako seznam seznamu map2_matice(P,I1,I2,O):-map2(map2(P),I1,I2,O). plus_matice(M1,M2,M):-map2_matice(plus,M1,M2,M). plus(X1,X2,X3):- X3 is X1 + X2. map2(_P,[],[],[]). map2( P,[I|Is],[J|Js],[O|Os]):- mycall2(P,[I,J,O]),map2(P,Is,Js,Os). % nebo: call(P,I,.J,O) nasobmat(C,M1,M0):-map(map(mult( C)),M1,M0). %násobení matice konstantou mult(C,X1,X0):- X0 is C * X1. • musíme změnit/zobecnit mycall mycall2(P,Args):- % P je jméno jednoho již definovaného predikátu, srv. FP: anonymní fce P=.. [Pred|Args0], % args bez volných proměnných append(Args0,Args,Args1), C=..[Pred|Args1], call(C). • předávané predikátové argumenty by měli být bez volných proměnných • volné proměnné jsou sdílené mezi všemi voláními, neproběhne přejmenování proměnných => často nežádoucí chování, náchylné k chybám
(Parametrické zpracování seznamu) • funkční symbol je relace mezi složkami a celou strukturou • f.s. nahradíme jinou relací - předanou parametrem zpracuj(Snil,_Scons,[],Snil). zpracuj(Snil, Scons,[I|Is],O):- zpracuj(Snil,Scons,Is,O1), mycall(Scons,[I,O1,O]). suma(I,O):-zpracuj(0,plus,I,O). length(I,O):-zpracuj(0,plus1,I,O). mappend(I,O):-zpracuj([],append,I,O). plus(X,Y,Z):-Z is X+Y. plus1(_X,Y,Z):-Z is Y+1.
(Parametrické zpracování seznamu II) • idea zpracuj: (anglicky fold) • zpracuj(E, , [X1,.., Xn], Out) • Out := X1 (X2 ( ...(Xn E)..)) • relace: (Xn,E,A1), (Xn-1,A1,A2),.. (X1,An-1,An),An=Out • jiná relace: R(X1,E,A1), R(X2,A1,A2),.. R(Xn,An-1,An),An=Out • další varianty filter(_P,[],[]). filter( P,[I|Is],O):- (mycall(P,[I]) -> O=[I|O1] ; O=O1), filter(P,Is,O1).