1 / 46

VI. Meta-cláusulas

VI. Meta-cláusulas. Jorge Cabrera Gámez Departamento de Informática y Sistemas Universidad de Las Palmas de Gran Canaria. Índice. Manipulación de la base de datos Declaración de propiedades de predicados Construcción y descomposición de términos

jaimie
Download Presentation

VI. Meta-cláusulas

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. VI. Meta-cláusulas Jorge Cabrera Gámez Departamento de Informática y Sistemas Universidad de Las Palmas de Gran Canaria Prolog VI

  2. Índice. • Manipulación de la base de datos • Declaración de propiedades de predicados • Construcción y descomposición de términos • Como obtener todas las respuestas sin • backtracking: bagof, setof y findall Prolog VI

  3. Manipulación de la base de datos Programa Prolog <----> Base de datos Base de datos: Conjunto de cláusulas que hemos ensamblado antes de iniciar la ejecución del programa. Prolog dispone de un conjunto de predicados predefinidos para modificar la base de datos de forma dinámica Prolog VI

  4. asserta(X) Añade la cláusula X como la primera cláusula de este predicado. Como otros predicados de E/S siempre falla en el backtracking y no deshace sus propios cambios. assertz(X) Como asserta/1, sólo que añade la cláusula X como la última cláusula del predicado. retract(X) Borra la cláusula X de la base de datos. Como en los casos anteriores no es posible deshacer los cambios debidos a este predicado en el backtraking. Prolog VI

  5. Ejemplo: ?- más_lento(A,B). A = juan B = ana ; No ?- más_lento(A,B). A = juan B = ana ; A = juan B = patricia ; No ?- más_rápido(A,B). A = ana B = juan ; A = patricia B = juan ; No ?- listing(rápido). rápido(patricia). Yes ?- más_rápido(A,B). A = patricia B = juan ; No ?- más_rápido(A,B). A = patricia B = juan ; A = patricia B = tomás ; No ?- más_rápido(A,B). No ?- más_lento(A,B). [WARNING: Undefined predicate: `más_lento/2'] No rápido(ana). lento(juan). más_lento(X,Y):- lento(X), rápido(Y). ?- assertz(lento(tomás)). Yes ?- listing(lento). lento(juan). lento(tomás). Yes ?- retract( | (más_lento(X,Y):- | lento(X), rápido(Y))). X = _G339 Y = _G340 Yes ?- assert((rápido(patricia))). Yes ?- listing(rápido). rápido(ana). rápido(patricia). Yes ?- assert( | (más_rápido(X,Y):- | rápido(X),lento(Y))). ?- listing(más_rápido). más_rápido(A, B) :- rápido(A), lento(B). Yes ?- listing(rápido). rápido(ana). rápido(patricia). Yes ?- retract(rápido(ana)). Yes ?- retractall(lento(X)). Yes ?- listing(lento). Yes Prolog VI

  6. ¿Es posible definir variables globales en Prolog? Ejemplo adaptado del tutorial de Amzi Prolog :-dynamic aquí/1. ir(Lugar):- puedo_ir(Lugar), moverse(Lugar). puedo_ir(Lugar):- aquí(X), conectado(X, Lugar). conectado(cocina, recibidor). conectado(recibidor, cocina). conectado(cocina, despensa). conectado(despensa, cocina). conectado(cocina, comedor). conectado(comedor, cocina). conectado(comedor, estar). conectado(estar, comedor). aquí(cocina). moverse(Lugar):- retract(aquí(_)), asserta(aquí(Lugar)). SWI-Prolog Prolog VI

  7. M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] M = [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)] A B C Torres de Hanoi Prolog VI

  8. Otro uso interesante: Memorización hanoi_nm(N,A,B,C,Movimientos) Movimientos es la secuencia de movimientos requeridos para mover N discos del poste A al poste B usando el poste C como intermediario de acuerdo con las reglas del puzzle de las Torres de Hanoi /* Sin memorización */ :- op(1000, xfx, to). hanoi_nm(1,A,B,C,[A to B]). hanoi_nm(N,A,B,C,Movimientos) :- N > 1, N1 is N-1, hanoi_nm(N1,A,C,B,Ms1), hanoi_nm(N1,C,B,A,Ms2), append(Ms1,[A to B|Ms2], Movimientos). SWI-Prolog Prolog VI

  9. Otro uso interesante: Memorización hanoi_nm(N,A,B,C,Movimientos) Movimientos es la secuencia de movimientos requeridos para mover N discos del poste A al poste B usando el poste C como intermediario de acuerdo con las reglas del puzzle de las Torres de Hanoi /* Con memorización */ :- dynamic hanoi/5. :- op(1000, xfx, to). hanoi(1,A,B,C,[A to B]). hanoi(N,A,B,C,Moves) :- N > 1, N1 is N-1, hanoi(N1,A,C,B,Ms1), hanoi(N1,C,B,A,Ms2), append(Ms1,[A to B|Ms2], Moves), lema(hanoi(N,A,B,C,Moves)). lema(P) :- asserta((P :- !)). SWI-Prolog Prolog VI

  10. Aún con la memorización, la solución no es perfecta, pues las soluciones que se memorizan son soluciones de N discos y una secuencia determinada de postes. Por ejemplo, la solución de hanoi_ng(3,a,b,c,Moves) generará las siguientes definiciones: hanoi_ng(3, a, b, c, [ (a to b), (a to c), (b to c), (a to b), (c to a), (c to b), (a to b)]) :- !. hanoi_ng(2, c, b, a, [ (c to a), (c to b), (a to b)]) :- !. hanoi_ng(2, a, c, b, [ (a to b), (a to c), (b to c)]) :- !. Es fácil advertir que cuando se tenga que resolver el problema con 4 discos, hanoi_ng(4,a,b,c,Moves), no será posible utilizar el problema de orden 3 ya resuelto porque las identidades de los postes no coinciden. Concretamente, Sería necesario tener resueltos estos dos problemas: hanoi_ng(3,a,c,b,Ms) y hanoi_ng(3,c,b,a,Ms) Nótese como el programa memoriza dos soluciones diferentes para el problema de dos discos. Prolog VI

  11. Para resolver este problema debemos “generalizar” la solución descubierta para un problema concreto (cierta secuencia de postes): % Sustituye en la secuencia de movimientos (solución) % el nombre de un poste por una variable equivalente. subsWithVariable([],_,[]):-!. subsWithVariable([(X to Y)|Ms],Assocs,[(VX to VY)|VMs]):- find_assoc(X,Assocs,VX), find_assoc(Y,Assocs,VY), subsWithVariable(Ms,Assocs,VMs). find_assoc(A,[(A,VA)|_],VA):-!. find_assoc(A,[_|Assocs],VA):- find_assoc(A,Assocs,VA). Por ejemplo: 6 ?- hanoi_nm(2,a,b,c,M1s), | subsWithVariable(M1s,[(a,A),(b,B),(c,C)],Moves). M1s = [ (a to c), (a to b), (c to b)], Moves = [ (A to C), (A to B), (C to B)]. Prolog VI

  12. %------------------------------------------------- % Con memorización y generalización %------------------------------------------------- hanoi(1,A,B,_,[A to B]):- !. hanoi(N,A,B,C,Moves) :- N > 1, N1 is N-1, hanoi(N1,A,C,B,Ms1), hanoi(N1,C,B,A,Ms2), append(Ms1,[A to B|Ms2], Moves), lema(hanoi(N,A,B,C,Moves)). lema(hanoi(N,P1,P2,P3,Moves)) :- subsWithVariable(Moves,[(P1,A),(P2,B),(P3,C)],VMoves), asserta((hanoi(N,A,B,C,VMoves):- !)). Prolog VI

  13. Otro ejemplo de Memorización %---------------------------- % Computes the next prime % number and updates the % list of prime numbers %---------------------------- find_next_prime(P,NP):- primes(Ps), NP is P+1, \+is_div(NP,Ps), !, append(Ps,[NP],EPs), update_primes(EPs). find_next_prime(P,NP):- NC is P+1, find_next_prime(NC,NP). %---------------------------- % Updates (memoizes) a new % list of prime numbers %---------------------------- update_primes(Ps):- ignore(retract(primes(_))), assert(primes(Ps)). :- dynamic primes/1. %---------------------------- % An initial list of prime % numbers. It grows as needed %---------------------------- primes([2,3,5,7,11,13,17,19]). %---------------------------- % next_prime(P,NP) returns % in NP the first prime % number that is greater than % P %---------------------------- next_prime(P,NP):- primes(Ps), append(_,[P,NP|_],Ps), !. next_prime(P,NP):- find_next_prime(P,NP). Prolog VI

  14. Otros predicados para manipulación de la base de datos (SWI-Prolog) retract/assert: modificar la base de datos de cláusulas. compilan el término que se les pasa como argumento. son costosas. recorda/erase: permiten grabar/borrar una base de datos de términos. mecanismo más rápido que assert/retract, pero no son cláusulas del programa Prolog VI

  15. recorda(+Key, +Term) recorded(+Key, -Valor, -Referencia) ?- progenitor(A,B). [WARNING: Undefined predicate: `progenitor/2'] No ?- listing(progenitor). [WARNING: No predicates for `progenitor'] No ?- recorded(prg,V,R), V=progenitor(luis,_),erase(R). V = progenitor(luis, pedro) R = 1733389 ; No ?- recorded(prg,V,R). V = progenitor(maría, pedro) R = 1734589 ; No ?- recorded(prg,V,R), assert(V). V = progenitor(maría, pedro) R = 1734589 ; No ?- progenitor(X,Y). X = maría Y = pedro ; No ?- recorda(prg,(progenitor(maría,pedro))). Yes ?- recorda(prg,(progenitor(luis,pedro))). Yes ?- recorded(prg,Valor,Referencia). Valor = progenitor(maría, pedro) Referencia = 1734589 ; Valor = progenitor(luis, pedro) Referencia = 1733389 No Prolog VI

  16. erase(+Referencia) • Puede emplearse tanto con términos, como con cláusulas. • abolish(:PredicateIndicator) • Elimina todas las cláusulas de un predicado de functor Functor y aridad Aridad de la base de datos. Todos los atributos de predicado (dynamic, multifile, index, etc.) toman su valor por defecto. “Abolir” un predicado importado sólo elimina el enlace importado; el predicado mantendrá su antigua definición en el módulo donde se define. • De acuerdo con el estándar ISO, abolish/1 sólo puede emplearse sobre predicados dinámicos. Esto es extraño, ya que para manejar este tipo de predicados ya se dispone de retract/1 y retractall/1. El predicado abolish/1 se introdujo en el DEC-10 Prolog precisamente para operar con definiciones estáticas. En SWI-Prolog, abolish/1 funciona sobre procedimientos estáticos, a menos el “flag” iso se fije a true. • Se aconseja emplear retractall/1 para borrar todas las cláusulas de un predicado dinámico. Prolog VI

  17. flag(+Key, -Old, +New) Key is an atom, integer or term. As with the recorded database, if Key is a term, only the name and arity are used to locate the flag. Unify Old with the old value associated with Key. If the key is used for the first time Old is unified with the integer 0. Then store the value of New, which should be an integer, float, atom or arithmetic expression, under Key. flag/3 is a fast mechanism for storing simple facts in the database. The flag database is shared between threads and updates are atomic, making it suitable for generating unique integer counters. clause(?Head, ?Body) Succeeds when Head can be unified with a clause head and Body with the corresponding clause body. Gives alternative clauses on backtracking. For facts Body is unified with the atom true. Normally clause/2 is used to find clause definitions for a predicate, but it can also be used to find clause heads for some body template. clause(?Head, ?Body, ?Reference) Equivalent to clause/2, but unifies Reference with a unique reference to the clause (see also assert/2, erase/1). If Reference is instantiated to a reference the clause's head and body will be unified with Head and Body. Prolog VI

  18. Síntesis dinámica de reglas :- dynamic testme/0. knot(1, fetch(Variable)). knot(2, write(Variable)). dynrule :- knot(1, Rule1), knot(2, Rule2), assert(( testme :- Rule1, Rule2 )), listing(testme), testme. fetch(A) :- A = 4. ?- dynrule. testme :- fetch(A), write(B). _L114 Yes Prolog VI

  19. :- dynamic testme/0. knot(1, X, fetch(X)). knot(2, X, write(X)). dynrule :- knot(1, X, Body1), % NOT Rule1, because it isn't a rule knot(2, X, Body2), % NOT Rule2, because it isn't a rule assert(( testme :- Body1, Body2 )), listing(testme), testme. fetch(4). ?- dynrule. testme :- fetch(A), write(A). 4 Yes Prolog VI

  20. Declaración de propiedades de predicados :- dynamic :- multifile :- index(+Head) • :- dynamic • aquí/0, • baz/2. • dynamic +Functor/+Arity, \ldots • Informa al intérprete que la definición de los • predicados puede cambiar durante la ejecución • (mediante assert/retract) • :- multifile • antepasados/2. • multifile +Functor/+Arity, \ldots • Informa al intérprete que la definición de los • predicados involucra más de un fichero. Esto • evita la redefinición un predicado cuando se • encuentra una nueva definición en otro fichero. Prolog VI

  21. %Fichero uno.pl :- multifile p/1. :-ensure_loaded(’dos.pl'). p(a). p(b). p(X) :- q(X), b(_). q(a). b(c). %Fichero dos.pl p(_) :- b(d). b(d). ?- [uno]. dos.pl compiled, 0.05 sec, 620 bytes. [WARNING: (c:/uno.pl:9) Redefined: b/1] c:/uno.pl compiled, 0.05 sec, 1,296 bytes. ?- listing(p). p(A) :- b(d). p(a). p(b). p(A) :- q(A), b(B) Yes ?- listing(b). b(c). Yes Prolog VI

  22. Declaración de propiedades de predicados :- dynamic :- multifile :- index(+Head) :- index(sub_type(1, 1)). sub_type(horse, animal). ... ... • :- index(+Head) • Indiza las cláusulas del predicado con el mismo nombre y aridad que el argumento utilizando los valores de los argumentos. • Permite especificar sobre qué argumentos se indiza este predicado (de los 32 primeros, máx. 4). • Útil en predicados definidos mediante numerosos hechos. Prolog VI

  23. Construcción y descomposición de términos Existen tres predicados predefinidos para descomponer términos o construir nuevos términos: Term =.. L functor(Term, F, N) arg(N, Term, A) Prolog VI

  24. ?- f(a,b) =.. L. L = [f, a, b] ?- T =.. [progenitor, miguel, maría ] T = progenitor(miguel, maría) ?- Z =.. [p, X, g(X,Y) ]. Z = p(X, g(X,Y)) ¿Por qué nos puede interesar descomponer un término en sus componentes? ¿Por qué nos puede interesar construir un nuevo término a partir de un functor y sus argumentos? Prolog VI

  25. Ejemplo: • Consideremos un programa que manipula figuras • geométricas como cuadrados, círculos, ... , que se • representan por un functor que indica el tipo de • figura y unos argumentos que la definen: • cuadrado(Lado) • triángulo(Lado1, Lado2, Lado3) • círculo(Radio) • Una de las operaciones a realizar sobre las figuras • aumenta(Fig, Factor, Fig1) Prolog VI

  26. Ejemplo: (Cont.) Una posibilidad: aumenta(cuadrado(A), F, cuadrado(A1)) :- A1 is A*F. aumenta(círculo(R), F, circulo(R1)) :- R1 is R*F. aumenta(rectángulo(A,B), F, rectángulo(A1,B1)) :- A1 is A*F, B1 is B*F. ... Funcionaría, pero no es elegante. Especialmente si el número de figuras es grande. Prolog VI

  27. Ejemplo: (Cont.) Un intento para agrupar todas figuras que estén parametrizadas por un único parámetro: aumenta(Tipo(Par), F, Tipo(Par1)) :- Par1 is Par*F. No está permitido en Prolog ya que el functor debe ser un átomo y no una variable. Prolog VI

  28. Ejemplo: (Cont.) La solución: aumenta(Fig, F, Fig1) :- Fig =.. [Tipo | Parámetros], multiplica_lista(Parámetros, F, Parámetros1), Fig1 =.. [Tipo | Parámetros1]. multiplica_lista([ ],_, [ ]). multiplica_lista([ X | L], F, [ X1 | L1]) :- X1 is F*X, multiplica_lista( L, F, L1). Prolog VI

  29. Ejemplo: Intentemos definir el predicado sustituye(Subterm, Term, Subterm1, Term1) Term1 se obtiene de la sustitución de todas las ocurrencias de Subterm en Term por Subterm1. ?- sustituye(sen(x), 2*sen(x)*f(sen(x)), p, F). F = 2*p*f(p) Prolog VI

  30. Ejemplo: ?- sustituye(a+b, f(a, A+B), v, F). A = a B = b F = f(a, v) ?- sustituye(a+b, A+B, v, F). A = a B = b F = v Prolog VI

  31. Ejemplo: sustituye(Subterm, Term, Subterm1, Term1) Si Subterm = Term entonces Term1 = Subterm1 en otro caso Si Term es atómico entonces Term1 = Term en otro caso la sustitución debe realizarse en los argumentos de Term ?- 2*sen(x)*f(sen(x)) =.. [F | Args]. F = * Args = [2*sen(x), f(sen(x))] Prolog VI

  32. ?- 2*sen(x)*f(sen(x)) =.. [F | Args]. F = * Args = [2*sen(x), f(sen(x))] ?- sustituye(mi, [mi,perro, [en,mi,casa]], tu, F). F = [tu, perro, [en, tu, casa]] Yes Ejemplo: sustituye(Term, Term, Term1, Term1):- !. sustituye(_, Term, _, Term):- atomic(Term),!. sustituye(Sub, Term, Sub1, Term1):- Term =.. [F | Args], sust_lista(Sub, Args, Sub1, Args1), Term1 =.. [F | Args1]. sust_lista(_,[ ],_,[ ]). sust_lista(Sub,[Term|Terms], Sub1, [Term1|Terms1]) :- sustituye(Sub, Term, Sub1, Term1), sust_lista(Sub, Terms, Sub1, Terms1). Prolog VI

  33. ¿Por qué no funciona sustituye/4 en el este caso? ?- sustituye(sen, sen(x), p, F). F = sen(x) ?- sustituye(sen, sen(x), p, F). F = p(x) sustituye(Term, Term, Term1, Term1):- !. sustituye(_, Term, _, Term):- atomic(Term),!. sustituye(Sub, Term, Sub1, Term1):- Term =.. [F | Args], sustituye(Sub, F, Sub1, F1), sust_lista(Sub, Args, Sub1, Args1), Term1 =.. [F1 | Args1]. sust_lista(_,[ ],_,[ ]). sust_lista(Sub,[Term|Terms], Sub1, [Term1|Terms1]) :- sustituye(Sub, Term, Sub1, Term1), sust_lista(Sub, Terms, Sub1, Terms1). Prolog VI

  34. Más ejemplos con univ (=..) ... :- op(100, xfx, isf). R isf OPs :- ( OPs =.. [F, A, C/D], integer(A) -> OPs1 =.. [F, A/1,C/D] ; OPs =.. [F, A/B, C], integer(C) -> OPs1 =.. [F, A/B,C/1] ), !, R isf OPs1. R isf OPs :- OPs =.. [_, A, B], integer(A), integer(B), !, R is OPs. R isf OPs:- OPs =..[F,A,B], R1 isf A, R2 isf B, OPs1 =..[F,R1,R2], R isf OPs1. Prolog VI

  35. Un uso habitual de =.. es el de sintetizar nuevos objetivos: obtener(Functor), calcular(ArgList), Objetivo =.. [Functor | ArgList] Objetivo o alternativamente, si sintácticamente se requiere que el functor principal de un objetivo sea un átomo, call(Objetivo) Prolog VI

  36. Otras veces nos interesará extraer el functor principal de un término Se puede emplear =.., pero suele ser más práctico y eficiente emplear functor y arg. functor(Term, F, N) es cierto si F es el functor principal de Term y N es la aridad de F arg(N, Term, A) es cierto si A es el N-ésimo argumento de Term cuando los argumentos se numeran de izda a dcha empezando por 1. Prolog VI

  37. Ejemplo: ?- functor( t( f(X), X, t), Fun, Arity). Fun = t Arity = 3 ?- arg( 2, f( X, t(a), t(b)), Y). Y = t(a) ?- functor( D, fecha, 3), | arg(1,D,29), arg(2,D, junio), arg(3,D,1998). D = fecha(29, junio, 1998) Prolog VI

  38. Cómo cambiar un argumento (I) setarg/3: deshace las asignaciones en el backtraking ?- F = f( X, t(a), t(b)), setarg(2,F,t(c)). F = f(X, t(c), t(b)) Yes setarg(+Arg, +Term, +Value) Extra-logical predicate. Assigns the Arg-th argument of the compound term Term with the given Value. The assignment is undone if backtracking brings the state back into a position before the setarg/3 call. See also nb_setarg/3. This predicate may be used for destructive assignment to terms, using them as an extra-logical storage bin. Always try hard to avoid the use of setarg/3 as it is not supported by many Prolog systems and one has to be very careful about unexpected copying as well as unexpected not copying of terms. Prolog VI

  39. Cómo cambiar un argumento (II) nb_setarg/3: NO deshace las asignaciones en el backtraking ?- F = f( X, t(a), t(b)), nb_setarg(2,F,t(c)). F = f(X, t(c), t(b)) Yes nb_setarg(+Arg, +Term, +Value) Assigns the Arg-th argument of the compound term Term with the given Value as setarg/3, but on backtracking the assignment is not reversed. If Term is not atomic, it is duplicated using duplicate_term/2. This predicate uses the same technique as nb_setval/2. We therefore refer to the description of nb_setval/2 for details on non-backtrackable assignment of terms. This predicate is compatible to GNU-Prolog setarg(A,T,V,false), removing the type-restriction on Value. See also nb_linkarg/3. Below is an example for counting the number of solutions of a goal. Note that this implementation is thread-safe, reentrant and capable of handling exceptions. Realising these features with a traditional implementation based on assert/retract or flag/3 is much more complicated. Prolog VI

  40. Como obtener todas las respuestas sin backtracking Una forma de obtener “todas las respuestas”: * Agotar las posibilidades de vuelta-atrás Otra: * Emplear los predicados bagof, setof y findall Prolog VI

  41. ?- bagof(Verdura, | item(Verdura,Precio), L). Verdura = _G315 Precio = 300 L = [coliflor] ; Verdura = _G315 Precio = 275 L = [pimiento] ; Verdura = _G315 Precio = 115 L = [lechuga] ; Verdura = _G315 Precio = 120 L = [tomates, cebolla] ; No ?- bagof(Verdura, | item(Verdura,Precio), L). Verdura = _G315 Precio = 300 L = [coliflor] ; Verdura = _G315 Precio = 275 L = [pimiento] ; Verdura = _G315 Precio = 115 L = [lechuga] ; Verdura = _G315 Precio = 120 L = [tomates, cebolla] ; No Las diferentes soluciones agrupadas por el valor de Precio • bagof(X, P, L) • Produce la lista L de todos los objetos X que satisfacen el objetivo P. Normalmente X es una variable en P. item(tomates, 120). item(coliflor, 300). item(pimiento, 275). item(lechuga, 115). item(cebolla, 120). ?- bagof(Verdura, item(Verdura,120), L). Verdura = _G297 L = [tomates, cebolla] Yes ?- bagof(Verdura, Precio ^ item(Verdura, Precio), L). Verdura = _G351 Precio = _G352 L = [tomates, coliflor, pimiento, lechuga, cebolla] ?- bagof(Precio,Verdura ^ item(Verdura,Precio), L). Precio = _G352 Verdura = _G351 L = [120, 300, 275, 115, 120] ?- bagof(Precio,Verdura ^ item(Verdura,50),L). No bagof(Verdura, item(Verdura,115), L). Prolog VI

  42. ?- setof(Precio,Verdura ^ item(Verdura,Precio), L). Precio = _G352 Verdura = _G351 L = [115, 120, 275, 300] (nótese la eliminación de duplicados y la ordenación de menor a mayor) ?- setof(Verdura,Precio ^ item(Verdura,Precio), L). Verdura = _G351 Precio = _G352 L = [cebolla, coliflor, lechuga, pimiento, tomates] (nótese la ordenación alfabética) • setof(X, P, L) • Produce la lista L de todos los objetos X que satisfacen el objetivo P. Normalmente X es una variable en P. Similar a bagof, pero ahora se eliminan los duplicados y los elementos de la lista se ordenan: alfabéticamente y de menor a mayor. item(tomates, 120). item(coliflor, 300). item(pimiento, 275). item(lechuga, 115). item(cebolla, 120). Prolog VI

  43. ?- findall(Verdura,item(Verdura,_),L). Verdura = _G273 L = [tomates, coliflor, pimiento, lechuga, cebolla] Yes ?- findall(Verdura,item(Verdura,50),L). Verdura = _G279 L = [ ] Yes • findall(X, P, L) • Produce la lista L de todos los objetos X que satisfacen el objetivo P. Si el objeto X no verifica P, findall se verifica con L = [ ] ?- findall(Precio,item(_,Precio),L). Precio = _G262 L = [120, 300, 275, 115, 120] Yes Similar a bagof y setof, pero ahora se incluyen en la lista todos los elementos, incluso aquellas soluciones que difieren en otras variables de P item(tomates, 120). item(coliflor, 300). item(pimiento, 275). item(lechuga, 115). item(cebolla, 120). Prolog VI

  44. Otro ejemplo inspirado en el ejemplo del restaurante Problema: Definir el predicado calorias_conocidas/0 que indique todos los platos que no disponen de la correspondiente definición de calorias % menu entrada(paella). entrada(gazpacho). entrada(langostinos). entrada(consome). entrada('sopa de fideos'). carne(filete_de_cerdo). carne(solomillo). carne(pollo_asado). pescado(trucha). pescado(bacalao). postre(flan). postre(natilla). postre(nueces_con_miel). postre(naranja). % Valor calorico de una racion calorias(paella, 200). calorias(gazpacho, 150). calorias(consome, 300). calorias(filete_de_cerdo, 400). calorias(pollo_asado, 280). calorias(trucha, 160). calorias(bacalao, 300). calorias(flan, 200). calorias(nueces_con_miel, 500). calorias(naranja, 50). Prolog VI

  45. 7 ?- | calorias_conocidas. No hay definición de calorias para "langostinos". No hay definición de calorias para "sopa de fideos". No hay definición de calorias para "solomillo". No hay definición de calorias para "natilla". Yes % % Verificación de que todos los platos % disponen de la correspondiente definición % de calorías % calorias_conocidas :- verifica_plato(entrada), verifica_plato(carne), verifica_plato(pescado), verifica_plato(postre). verifica_plato(Plato):- P =..[Plato, E], setof(E,P,Es), verifica_cal(Es). verifica_cal([E|Es]):- ( calorias(E,_) -> true ; format('No hay definición de calorias para \”~w\”.~n',[E]) ), verifica_cal(Es). verifica_cal([]). Prolog VI

  46. Sumario. • Las implementaciones de Prolog proporcionan un • conjunto de predicados metalógicos sumamente útiles. • Que permiten construir o descomponer términos • utilizando el operador =.., functor o arg. • Que permiten modificar la base de datos clausal • utilizando assert, retract y sus variantes. • Que proporcionan listas de objetos que satisfacen una • cierta condición empleando bagof, setof o findall. Prolog VI

More Related