220 likes | 294 Vues
Vestavěné predikáty a jejich použití (5). Jan Hric, KTI MFF UK, 1997- 20 10a http://kti.ms.mff.cuni.cz/~hric. 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í
E N D
Vestavěné predikáty a jejich použití (5) Jan Hric, KTI MFF UK, 1997-2010a http://kti.ms.mff.cuni.cz/~hric
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, @>/2, @=</2, @>=/2 • vzestupné pořadí: • proměnné podle adresy • atomy .. ascii hodnoty lexikograficky • řetězce .. dtto • čísla (int, float) .. hodnoty • struktury .. dtto • (LPA) konjunkce @< 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. d051031 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ě: .<EOF> 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)