Vestavěné predikáty a jejich použití (5) Jan Hric, KTI MFF UK, a
Vestavěné predikáty aritmetika výpočty, porovnávání vstup/výstup spracování termů a atomů testy druhu, porovnávání, vytváření a dekompozice řízení spracování + práce s databází práce s množinami řešení
Uspořádání termů =/2 vzestupné pořadí: proměnnépodle adresy atomy.. ascii hodnoty lexikograficky řetězce.. dtto čísla(int, float).. hodnoty struktury.. dtto (LPA) disjunkce compare(Rel,T1,T2) Rel je
Compare/3 - idea použití umožňuje získat explicitní informaci o porovnání (tj. jako data místo stavu programu) vs. výsledek porovnání je dán postupem výpočtu (hodnotou “Instruction Pointer”) aritm_rozskok(X,Y):- compare(Rel,X,Y), rozskok(Rel,X,Y). rozskok(<,X,Y):- spracuj_X<Y. rozskok(=,X,Y):- spracuj_X=Y. rozskok(>,X,Y):- spracuj_X>Y.
Test shody termů = vykoná unifikaci (a případně substituce) chceme: test termů (s proměnnými) na shodu bez vykonání unifikace ==/2, \==/2 ?- X=Y. uspěje ?- X==Y. neuspěje ?- X=Y, X==Y. uspěje X = Y = _1 odpověď
Test typu termu atom/1 argument je atom atomic/1 arg. je konstanta, atom nebo číslo integer/1, float/1, number/1 var/1, nonvar/1, ground/1 (LPA) type(Term,Typ) vráti typ termu compound/1 arg. je složený, tj. neprázdný seznam nebo struktura
Rozbor složených termů functor(Term, Functor, Arita) k termu určí funktor a aritu; mod (+,?,?) k funktoru a aritě vytvoří term; mod (?,+,+) arg(+N,+Term,?Argument) vybere n-tý arg. z Termu a unifikuje s Argument X=..L % „univ“, mody (+,?) nebo (?,+) rozloží strukturu X na seznam funktor a argumenty ?- f(a,g(b))=.. [f,a,g(b)] ?- [a,b]=..[.,a,[b]] Nepoužívat, pokud je funkční s. známý (např. seznamy, bin. stromy, log. fle) Určeno pro situace, kdy je vstup obecný term (s lib. funk. symboly) např: unifikace (viz), crossreference programu/termu, zpracování programů …
Př.: Unifikace unify(X,Y):- atomic(X), atomic(Y), X=Y. unify(X,Y):- var(X), X=Y ; var(Y), Y=X. unify(X,Y):- % struktury X=..[FX|AX], Y=..[FY|AY], % rozebrání FX=FY, % shoda funktorů unify_arg(AX,AY). % kontroluje i stejný #arg. unify_arg([],[]). unify_arg([X|AX],[Y|AY]):- unify(X,Y), unify_arg(AX,AY). Idea: unify_arg(AX,AY):-foreach(unify,AX,AY).
Unifikace II unifikace struktur - varianta: unify(X,Y):- % struktury functor(X,FX,NX), functor(Y,FY,NY), FX=FY, % shoda funktorů NX=NY, % shoda počtu argumentů X=..[_FX|AX], Y=..[_FY|AY], % rozebrání unify_arg(AX,AY). % nepřímá rekurze Další varianty: viz Autotest
poznámky k foreach/3 Lepší abstrakce, standardní idiom Nemusí být podporováno jazykem I když konstrukci jazyk nepodporuje, lze ji považovat za makro a vygenerovat zdrojak Tj. (způsob) rozšíření jazyka V čistém Prologu (v logice 1. řádu) nejsou „funkcionální“ parametry -> opakování kódu Nahrazuje programování „kopírováním bloků“ ...
Převod textových reprezentací name(Konstanta,Retezec) mod (+,?) nebo (?,+) konstantu (atom, číslo) převede na řetězec znaků ?- name(abc,”abc”). ?- name(123,”123”). použití: generování nových (jmen) konstant, predikátů, kompaktní reprezentace slov/textu,... ale: nová jména: c(0) místo c0, vrchol(v,1) místo v1 Volba reprezentace: potřebné složky v termu datum(2005,10,31) vs. d vs. “d051031”,“05/10/31”
Operátory (pouze!) syntaktická konvence, syntaktický cukr umožňují pohodlnější zápis bez nadbytečných závorek (dělá to mnohem méně než si myslíte) nemění vnitřní reprezentaci termů (!) převod na vnitřní reprezentaci je (vždy) jednoznačný Zdrojový kód vs. právnické texty, přirozený jazyk, uživ. specifikace deklarace nezavede nový predikát/funkční symbol (!) nezmění (nerozšíří) chování is/2 lze použít pro termy i predikáty předdefinované operátory jsou i :- ;, ->
Deklarace operátorů :-op(Precedence, Druh, Jmeno). deklarace je součást zdrojového kódu (v souboru) deklarace se vykonává, proto je uvedena :- Nechci přidat fakt op/3, ale způsobit změnu interních tabulek Jmeno je jeden atom nebo seznam atomů; tyto atomy se (pře)deklarují s danou precedencí a asociativitou deklarace je globální, platí pro všechny další čtení (programu i dat) Precedence je přirozené číslo mezi 1 a 1200 (SWI, LPA) Vyšší precedence je výš v termu, tj. později se váže opačně než priorita v matematice Druh určuje druh a asociativitu (binární) infixní, (unární) pre-, postfixní doprava asociativní, doleva a., neasociativní
Operátory (pokrač.) vyjádření druhu a asociativity prefixní: fx fy mínus, negace postfixní: xf yf faktoriál infixní: xfy yfx xfx +, *, &, <, = pravěasoc.(^) levěasoc.(+) neasociativní (=) význam písmenek: f - poloha funktoru, x - term s ostře nižší precedencí, y - term s nižší nebo stejnou precedencí
Operátory (pokrač.) závorky mají přednost při určování struktury termu (jako obvykle) speciálně: precedence = 0 ruší deklaraci op. lexikální problém závorek, čárky a tečky f(...) versus op (...) % významná mezera před ( f(a,b) versus f((a,b)) …=f(’,’(a,b)) a.b.[] vs. a. b. [] % významná mezera za. (tečkou) - konec klauzule: tečka, bílý znak; chybně:. př.: :-op(500,yfx, [+,-]). a+b+c yfx: (a+b)+c /*předdefinováno*/ xfy: a+(b+c) a=b=c xfx není povoleno, musíme uvést závorky, jinak synt. chyba
Operátory Příklad: pro doménu výrokových logických formulí :- op(500,xfx,ekv). % neasociativní :- op(400,xfy,imp). % doprava: A imp (B imp C) :- op(300,yfx,or). % doleva: (A or B) or C :- op(290,yfx,and). :- op(200, fy,non). % fy umožní psát non non p(x) anebo :- op(500,xfx, ). :- op(400,xfy, =>). :- op(300,yfx, #). % or :- op(290,yfx, &). :- op(200, fy, \\\). % \\\ \\\ p(x) Umožnuje psát: eval( p(x)&p(y)=>p(y)&p(x), Prom,V). Místo: eval( =>(&(p(x),p(y)),&(p(y),p(x))), Prom,V). Přidání xor: :-op(301,yfx,xor). – pouze deklarace operátoru Všechny knihovní procedury musím změnit – přidat zpracování xor/2 Jiné domény: kompozice obrázků (vedle, nad, přes, …), …
Operátory - příklad zpracování množin (analogicky is/2 ): is_set/2 sjednocení \-/, průnik /-\, seznamy uspořádané vs. neuspořádané seznamy (ve skutečnosti asi Pascalská konvence +,*) :- op(700,xfx,is_set). :- op(510,yfx,/-\). :- op(511,yfx,\-/). :- op(512,fx,suma). X is_set X :- seznam(X). % lépe: list2set(X,X0) X is_set Y\-/Z :- VY is_set Y, VZ is_set Z, sjednoceni(VY,VZ,X). /*mergesort*/ X is_set Y/-\Z :- VY is_set Y, VZ is_set Z, prunik(VY,VZ,X). X is_set suma Y:- VY is_set Y, suma_množiny(VY,X). ?- X is_set ([1,2]\-/[3,4]) /-\ [2,3]. ?- is_set(X, /-\( \-/( [1,2], [3,4]), [2,3])).
Zjišťování definic operátorů current_op(Prec, Asoc, Jmeno) mod (?,?,?) vrací backtrackingem všechny aktuálně definované operátory ?- current_op(X,Y,is_set). ?- current_op(510,Y,Z). ?- current_op(X,Y,Z). všechny aktuálně definované operátory, viz následující tabulka
Předdefinované operátory (SWI) op( 200, xfx, **). op( 200, xfy, ^). op( 300, xfx, mod). /*LPA Prolog*/ op( 400, yfx, [ >, *, xor, mod, rem]). op( 500, yfx, [-, +, \/, /\]). op( 500, fx, [-, +, \, ?]). op( 600, xfy, : ). op( 700, xfx, [>, =, =, =:=, =\=, is, =.., ==, \== ]). op( 850, yfx, [~>, <~]). op( 900, fy, [spy, nospy, \+, not, one]). op(1000, xfy, ’,’). % =< jsou pred. spojky, () op(1050, xfy, -> ). op(1100, xfy, [’;’, ’|’]). op(1150, fx, [dynamic,public,multifile]). % a další op(1200, xfx, [:-, -->]). op(1200, fx, [:-, ?-]).
Operátory na úrovni cílů Příklad: (náchylné k chybám) a:- predzpracovani, % není součást testu, kvůli záv. ( test1->then1 % (1) závorky nutné ; test2->then2 % (2) syntakticky jsou ; a -> binární ; else ), postzpracovani.% není součást else Při zpracování prologovských programů: pokud se používají operátory (s prec. >= 1000) pro tvorbu klauzulí (tj. :-, ; ->) jako termy, musí se uzavřít do dodatečných závorek: testDisj((X ; Y)) :- …
(Operátory - dodatek) V Prologu jsou pouze infixové a unární operátory operátorovou syntaxi lze rozšířit operátory s více klíčovými slovy if _ then _ else distfixní (uzavřené) operátory i závorky lze takto chápat – např. XML uživatelské definice nových druhů závorek – např. pro speciální (vnořenou) syntax syntaktická analýza je (velmi) jednoduchá variabilní a opakované operátory seznamová notace jako operátor [, | ] dvourozměrná syntax (v Haskelli …) indentace namísto oddělovačů
Autotest unifikace pomocí přímého výběru unifikovaných argumentů použít arg/3 ve “for” cyklu podle počtu arg. pozbírat z termu všechny (konstanty, proměnné, podtermy) použití =.., var,... funkční symboly, s četností, s počtem výskytů funktor, is... (proměnné bez opakování) ==, = (navrhnout operátory pro bool. výrazy)