Lazy Functional Prolog: a Practical Approachgpd.sip.ucm.es/jaime/pda/frolog.pdf · 2013. 5. 14. ·...
Transcript of Lazy Functional Prolog: a Practical Approachgpd.sip.ucm.es/jaime/pda/frolog.pdf · 2013. 5. 14. ·...
Lazy Functional Prolog: a Practical Approach
J. Rodrıguez-Hortala, J. Sanchez-Hernandez
Dep. Sistemas Informaticos y ComputacionUniversidad Complutense de Madrid
PROLE 2007, Zaragoza 12-14 Septiembre 2007
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Motivacion (Programacion Logico Funcional)
Actualmente, PLF (Curry, Toy)
Haskell+
indeterminismo, vars. logicasrestricciones, . . .
Otra vision de PLF
Prolog+
funciones, orden superiorλ-abstracciones, pereza
Diferencia?
inclusion de Prolog en sentido propio: sintaxis de primer orden,corte, metaprogramacion, entrada salida de Prolog, etc
no hay tipos!!
Ademas: respetamos el mecanismo operacional de Prolog, pero
admitimos pereza anotada
Implementacion = traduccion de funciones a codigo Prolog(expansor Prolog).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Motivacion (Programacion Logico Funcional)
Actualmente, PLF (Curry, Toy)
Haskell+
indeterminismo, vars. logicasrestricciones, . . .
Otra vision de PLF
Prolog+
funciones, orden superiorλ-abstracciones, pereza
Diferencia?
inclusion de Prolog en sentido propio: sintaxis de primer orden,corte, metaprogramacion, entrada salida de Prolog, etc
no hay tipos!!
Ademas: respetamos el mecanismo operacional de Prolog, pero
admitimos pereza anotada
Implementacion = traduccion de funciones a codigo Prolog(expansor Prolog).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Motivacion (Programacion Logico Funcional)
Actualmente, PLF (Curry, Toy)
Haskell+
indeterminismo, vars. logicasrestricciones, . . .
Otra vision de PLF
Prolog+
funciones, orden superiorλ-abstracciones, pereza
Diferencia?
inclusion de Prolog en sentido propio: sintaxis de primer orden,corte, metaprogramacion, entrada salida de Prolog, etc
no hay tipos!!
Ademas: respetamos el mecanismo operacional de Prolog, pero
admitimos pereza anotada
Implementacion = traduccion de funciones a codigo Prolog(expansor Prolog).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Precedentes
Prolog + funciones definidas por el usuario ha sido propuestoantes (T. Asvanyi, 2003; A. Casas et al, 2006; etc).
A. Casas et al incluye lambda-abstracciones, orden superior yevaluacion perezosa (anotada)... basicamente lo que buscamos!
Nuestra propuesta se distingue fundamentalmente por:
tratamiento de HO (traduccion a 1er orden estilo Toy)
modelo de pereza (anotacion en constructoras en vez defunciones)
OCaml y otros admiten suspension de expresiones, pero:suspension/activacion explıcitas programas mas complicados
Nuestra propuesta
Automatiza la suspension/activacion (y ademas esta en uncontexto indeterminista).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Precedentes
Prolog + funciones definidas por el usuario ha sido propuestoantes (T. Asvanyi, 2003; A. Casas et al, 2006; etc).
A. Casas et al incluye lambda-abstracciones, orden superior yevaluacion perezosa (anotada)... basicamente lo que buscamos!
Nuestra propuesta se distingue fundamentalmente por:
tratamiento de HO (traduccion a 1er orden estilo Toy)
modelo de pereza (anotacion en constructoras en vez defunciones)
OCaml y otros admiten suspension de expresiones, pero:suspension/activacion explıcitas programas mas complicados
Nuestra propuesta
Automatiza la suspension/activacion (y ademas esta en uncontexto indeterminista).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Precedentes
Prolog + funciones definidas por el usuario ha sido propuestoantes (T. Asvanyi, 2003; A. Casas et al, 2006; etc).
A. Casas et al incluye lambda-abstracciones, orden superior yevaluacion perezosa (anotada)... basicamente lo que buscamos!
Nuestra propuesta se distingue fundamentalmente por:
tratamiento de HO (traduccion a 1er orden estilo Toy)
modelo de pereza (anotacion en constructoras en vez defunciones)
OCaml y otros admiten suspension de expresiones, pero:suspension/activacion explıcitas programas mas complicados
Nuestra propuesta
Automatiza la suspension/activacion (y ademas esta en uncontexto indeterminista).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Precedentes
Prolog + funciones definidas por el usuario ha sido propuestoantes (T. Asvanyi, 2003; A. Casas et al, 2006; etc).
A. Casas et al incluye lambda-abstracciones, orden superior yevaluacion perezosa (anotada)... basicamente lo que buscamos!
Nuestra propuesta se distingue fundamentalmente por:
tratamiento de HO (traduccion a 1er orden estilo Toy)
modelo de pereza (anotacion en constructoras en vez defunciones)
OCaml y otros admiten suspension de expresiones, pero:suspension/activacion explıcitas programas mas complicados
Nuestra propuesta
Automatiza la suspension/activacion (y ademas esta en uncontexto indeterminista).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Plan de la charla
Traduccion de funciones y predicados. Esquema basico.
Orden superior y λ-abstracciones.
Pereza anotada. Sharing.
Ejemplos. Rendimiento.
Conclusiones.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Traduccion de funciones elementales
Regla en sintaxis funcional:
f(A1, . . . , An)︸ ︷︷ ︸cabeza
= Exp︸︷︷︸cuerpo
:- C1, . . . , Cm︸ ︷︷ ︸condiciones
.
Traduccion (regla a regla):
f(A1, . . . , An, R) : − Ct1, . . . , C
tm, ExpR
anadir un argumento resultado Raplanar las llamadas a funcion de las condiciones Ci
traducir la expresion Exp dejando el resultado en R
fact(0) = 1.fact(N) = N*fact(N-1) :- N>0.
↓ traduccion (primitivas aritmeticas +,-. . . definidas en un preludio)
fact(0,R) :- R=1.fact(N,R) :- N>0, -(N,1,N1), fact(N1,R1), *(N,R1,R).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Interpretacion informal del significado de las funciones
Principio operacional 1: el orden de evaluacion de una funcion es:
paso de parametros (unificacion)︸ ︷︷ ︸(1)
- condiciones︸ ︷︷ ︸(2)
- cuerpo de la funcion︸ ︷︷ ︸(3)
Traduccion alternativa: intercambiar (2) y (3)cambia el comportamiento en presencia de cortes o noterminacion!ambas traducciones son aceptables, pero trabajamos con laprimera.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Interpretacion informal del significado de las funciones
Principio operacional 1: el orden de evaluacion de una funcion es:
paso de parametros (unificacion)︸ ︷︷ ︸(1)
- condiciones︸ ︷︷ ︸(2)
- cuerpo de la funcion︸ ︷︷ ︸(3)
Traduccion alternativa: intercambiar (2) y (3)cambia el comportamiento en presencia de cortes o noterminacion!ambas traducciones son aceptables, pero trabajamos con laprimera.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Traduccion de predicados
Para cada clausula:
aplanar las llamadas a funcion en las condiciones
doubleFact(N,M) :- fact(N)=F, M=2*F.
↓ traduccion
doubleFact(N,M) :- fact(N,F), *(2,F,M).
Los predicados Prolog se pueden “funcionalizar” con la primitiva:
proj(T,G) ::= evalua el objetivo G y devuelve el termino T
Por ejemplo, para extraer el functor ppal. y la aridad de un termino:
name and arity(Term) = proj((Name,Arity), functor(Term,Name,Arity)).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Orden superior
La aplicacion de una funcion parcial F a un argumento A sehace explıcita por medio de @ (“apply”): F@A.
Traduccion a primer orden (como en Toy): el sistema generalas clausulas para @.
map(F,[]) = [].
map(F,[X|Xs]) = [F@X|map(F,Xs)].
neg(L) = map(not,L).
not(true) = false.
not(false) = true.
↓ traduccion
map(F,[],[]).
map(F,[X|Xs],[Fx|Fxs]) :- @(F,X,Fx), map(F,Xs,Fxs).
neg(L,L1) :- map(not,L,L1). not(true,false). not(false,true).
@(map,F,map(F)).
@(map(F),L,L1) :- map(F,L,L1).
@(neg,L,L1) :- neg(L,L1).
@(not,X,Y) :- not(X,Y).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
λ-abstracciones
Sintaxis:
λx.e se escribe como fun(X,E)λx1 . . . xn.e se escribe fun(X1, . . . , Xn, E)
Traduccion (λ lifting):
Numerar (dar nombre) a cada ”fun”: fun1, fun2,. . .Introducir las llamadas y definiciones para fun1, fun2,. . .teniendo en cuenta las variables del contexto externo
f(L) = map(fun(X,X*2),L). g(X) = fun(Y,X+Y).
↓ λ-lifting
f(L) = map(fun1,L).fun1(X) = X*2.
g(X) = fun2(X).fun2(X,Y) = X+Y.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Evaluacion perezosa
Nuestras funciones son impacientes por defecto.
Pero no queremos renunciar a las posibilidades practicas queofrece la evaluacion perezosa, en particular a las estructurasde datos infinitas (o incompletas).
permitimos anotaciones explıcitas de pereza.
... pero, ¿donde localizamos la pereza? Dos alternativas:
46 en las funciones
X en las (constructoras de) estructuras de datos
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Anotaciones de pereza en las funciones
Traduccion directa con suspensiones Prolog (A. Casas et al, 2006):
freeze(Var,Goal) ::= suspende Goal hasta que V ar se ligue
:- lazy(from).from(N) = [N|from(N+1)].
take(0,L)=[]:-!.
take(N,[])=[]:-!.
take(N,[X|Xs])=[X|take(N-1,Xs)].
↓ se traduce como
from(N,L):- freeze(L,fromLazy(N,L)).fromLazy(N,[N|L]):- +(N,1,N1),from(N1,L).
take(0,L,R)...
...
take(3,from(1))trad from(1,L), take(3,L,K)
take(3,freeze(L, fromLazy(1 ,L))︸ ︷︷ ︸dem. por take
,K) from(2,M), take(3,[1|M],L)
∗ [1,2,3]
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en las funciones. Problemas
Criba de Eratostenes
primes = sieve(from(2)).
sieve([X|Xs])=[X|sieve(filter(fun(Y,mod(Y,X)=\=0), Xs))].
firstPrimes(N) = take(N,primes).
Funciones perezosas... cuales?
Sin ninguna declaracion de pereza loop!
from perezoso loop!! (filter demanda la la lista completa).
from y filter perezosos loop!!! (sieve demanda la evaluacionde la lista).
Todas las funciones perezosas funciona... muy ineficiente.
Conjunto mınimo de funciones perezosas en este caso:{from,filter , sieve}
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en constructoras. Ideas previas
En muchos ejemplos practicos la pereza es util para podermanipular estructuras de datos infinitas
pereza asociada a las constructoras.
La forma habitual de manejar pereza en lenguajes impacientes(como OCaml) es mediante anotaciones explıcitas de perezaen las declaraciones de tipo:
type ’a listL = Nil | Cons of (’a * (’a listL Lazy.t));;
let rec from n = Cons (n,lazy (fromL (n+1)));;
let rec take n lst = match n,lst with
,Nil -> Nil
| 0, -> Nil
| ,Cons (x,xs) -> Cons (x, lazy (take (n-1) (Lazy.force xs)));;
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en constructoras. Primera aproximacion
λ-abstracciones como suspensiones:
E se suspende como λx.E ≡ fun( , E)se despierta aplicandola a un argumento dummyfun( , E)@dummy E
Ejemplo: listas perezosas en el segundo argumento
from(N)= [N|from(N+1)].
take(0,L)= []:-!.
take(N,[])=[]:-!.
take(N,[X|Xs])=
[X|take(N-1,Xs)].
from(N)=[N|fun( ,from(N+1))].
take(0,L)=[]:-!.
take(N,[])=[]:-!.
take(N,[X|Xs])=
[X|fun( ,take(N-1,Xs@dummy))].
Objetivo: automatizar esta transformacion en presencia de ladeclaracion :- lazy([ |on]).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en constructoras. Primera aproximacion
λ-abstracciones como suspensiones:
E se suspende como λx.E ≡ fun( , E)se despierta aplicandola a un argumento dummyfun( , E)@dummy E
Ejemplo: listas perezosas en el segundo argumento
from(N)= [N|from(N+1)].
take(0,L)= []:-!.
take(N,[])=[]:-!.
take(N,[X|Xs])=
[X|take(N-1,Xs)].
from(N)=[N|fun( ,from(N+1))].
take(0,L)=[]:-!.
take(N,[])=[]:-!.
take(N,[X|Xs])=
[X|fun( ,take(N-1,Xs@dummy))].
Objetivo: automatizar esta transformacion en presencia de ladeclaracion :- lazy([ |on]).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en constructoras + indeterminismo = problemas
Ordenacion por permutacion (generate and test)
% generate
permut([]) = [].
permut([X|Xs]) = insert(X,permut(Xs)).
insert(X,[]) = [X].
insert(X,[Y|Ys]) = [X,Y|Ys].
insert(X,[Y|Ys]) = [Y|insert(X,Ys)].
% test
sorted([]) = true.
sorted([X]) = true.
sorted([X,Y|Ys]) = sorted([Y|Ys]) :- X=<Y.
sorted([X,Y|Ys]) = false :- X>Y.
pemutSort(Xs) = ifThen(sorted(Ys),Ys) :- Ys=permut(Xs).
permutSort([4,3,2,1],L) [1,2,3,4] (muy ineficiente!)
+ declaracion :- lazy([ |on]).permutSort([4,3,2,1],L) [1,4,3,2]. . . [1,2,3,4] (incorrecto)
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Pereza en constructoras sin sharing
En el ejemplo anterior, con listas perezosas tenemos:
permutSort([4,3,2,1])
↓ * pemutSort(Xs) = ifThen(sorted(Ys),Ys) :- Ys=permut(Xs).
ifThen(sorted([1|λ . permut([4, 3, 2])︸ ︷︷ ︸↓
[2,3,4]ordenado
])
︸ ︷︷ ︸↓
true
, [1|λ . permut([4, 3, 2])︸ ︷︷ ︸↓
[4,3,2]desordenado!!
] )
↓ ∗[1,4,3,2] (tambien [1,3,4,2],. . . , [1,2,3,4] run-time choice)
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
λ-abstracciones con comparticion: δ-abstracciones
Principio operacional 2 En programas terminantes (con evaluacionestricta) la evaluacion de una funcion debe producir el mismoresultado con o sin declaraciones de pereza (si el programa es noterminante la pereza puede evitar divergencias).
Necesitamos comparticion en las λ-abstracciones generadaspara suspender δ-abstracciones:
δ Ev Res . Exptrad funN (Ev,Res, , Exp).
Ev (flag): on si la suspension ya ha sido evaluada, var e.o.c.Res: resultado de la evaluacion (si Ev == on).
: argumento dummy como antes
Regla de evaluacion:
funN(Ev,Res,ExpRes)=H :- (Ev==on,!;ExpRes,Ev=on),H=Res.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
δ-abstracciones. Ejemplo
:- lazy([ |on]).
app([],Xs) = Xs.app([X|Xs],Ys) = [X|app(Xs,Ys)].
↓ traduccion
app([],Ys,Ys).app([X|Xs],Ys,[X|fun1(Ev,Res,Xs,Ys)]).fun1(Ev,Res,Xs,Ys,Dummy,H):-(Ev==on, !
;@(Xs,dummy,Xs1), app(Xs1,Ys,R1), H=R1, Ev=on
), H=Res.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Eficiencia. Pereza: funciones & constructoras
Goal Lazy funs (all) Lazy funs (some) Lazy listsnPrime(300) 0.829399 0.534276 0.182028nPrime(600) 2.65868 1.70961 0.697245
nPrime(1000) overflow overflow 1.92277nPrime(6000) overflow overflow 80.5051
firstPrimes(300) 1.06425 0.543337 0.230733firstPrimes(600) 3.58354 1.76382 0.899285
firstPrimes(1000) overflow overflow 2.19576firstPrimes(1200) overflow overflow 3.39396firstPrimes(1500) overflow overflow overflow
permutSort(revLst(10)) 0.365988 0.160308 0.195278permutSort(revLst(12)) 3.18058 1.44293 1.70397permutSort(revLst(15)) 96.7763 42.2988 49.6788permutSort(revLst(16)) 248.329 110.585 128.547
Tiempos de ejecucion (en segundos)
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Eficiencia. Toy & Prolog + funciones (pereza en constructoras)
Goal Toy Lazy listspermutSort(revLst(10)) 0.76 0.28permutSort(revLst(12)) 6.90 2.35permutSort(revLst(12)) 6.90 2.35permutSort(revLst(12)) 62.43 22.97
Es posible optimizar la traduccion de Toy (eliminando gestionde 6=, etc) y aumentar su rendimiento
Pero el modelo de pereza es esencialmente distinto
Definimos: fib(0)=0. fib(1)=1. fib(N)=fib(N-1)+fib(N-2).
Goal Toy Lazy listspermutSort([fib(22),fib(21),fib(20)]) 1.16 1.13permutSort([fib(26),fib(25),fib(24)]) overflow 7.65
Toy reevalua el calculo los elementos de la lista.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Eficiencia. Toy & Prolog + funciones (pereza en constructoras)
Goal Toy Lazy listspermutSort(revLst(10)) 0.76 0.28permutSort(revLst(12)) 6.90 2.35permutSort(revLst(12)) 6.90 2.35permutSort(revLst(12)) 62.43 22.97
Es posible optimizar la traduccion de Toy (eliminando gestionde 6=, etc) y aumentar su rendimiento
Pero el modelo de pereza es esencialmente distinto
Definimos: fib(0)=0. fib(1)=1. fib(N)=fib(N-1)+fib(N-2).
Goal Toy Lazy listspermutSort([fib(22),fib(21),fib(20)]) 1.16 1.13permutSort([fib(26),fib(25),fib(24)]) overflow 7.65
Toy reevalua el calculo los elementos de la lista.
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Mezclando impaciencia y pereza (I)
Triangulo de Pascal con listas perezosas (Blas et al):
1 row 01 1 row 1
1 2 1 row 21 3 3 1 row 3
1 4 6 4 1 row 4. . .
Idea:
0 1 3 3 1 [0] ++ row 3+ 1 3 3 1 0 row 3 ++ [0]
1 4 6 4 1 row 4
:- include(prelude). :- lazy([ |on]).
iter(F) = [F|iter(zipWith((+),[0|F],append(F,[0])))].
pas=iter([1]). row(N)=nth(N,pas). comb(N,M)=nth(M,(nth(N,pas))).
row(6) [1, 6, 15, 20, 15, 6, 1]
take(5,pas) [ [1]︸︷︷︸, [1, 1]︸︷︷︸, [1, 2, 1]︸ ︷︷ ︸, [1, 3, 3, 1]︸ ︷︷ ︸, [1, 4, 6, 4, 1]︸ ︷︷ ︸]
↘↓↙¿y si evaluamos las listas internas de modo impaciente?
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Mezclando impaciencia y pereza (I)
Triangulo de Pascal con listas perezosas (Blas et al):
1 row 01 1 row 1
1 2 1 row 21 3 3 1 row 3
1 4 6 4 1 row 4. . .
Idea:
0 1 3 3 1 [0] ++ row 3+ 1 3 3 1 0 row 3 ++ [0]
1 4 6 4 1 row 4
:- include(prelude). :- lazy([ |on]).
iter(F) = [F|iter(zipWith((+),[0|F],append(F,[0])))].
pas=iter([1]). row(N)=nth(N,pas). comb(N,M)=nth(M,(nth(N,pas))).
row(6) [1, 6, 15, 20, 15, 6, 1]
take(5,pas) [ [1]︸︷︷︸, [1, 1]︸︷︷︸, [1, 2, 1]︸ ︷︷ ︸, [1, 3, 3, 1]︸ ︷︷ ︸, [1, 4, 6, 4, 1]︸ ︷︷ ︸]
↘↓↙¿y si evaluamos las listas internas de modo impaciente?
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Mezclando impaciencia y pereza (I)
Triangulo de Pascal con listas perezosas (Blas et al):
1 row 01 1 row 1
1 2 1 row 21 3 3 1 row 3
1 4 6 4 1 row 4. . .
Idea:
0 1 3 3 1 [0] ++ row 3+ 1 3 3 1 0 row 3 ++ [0]
1 4 6 4 1 row 4
:- include(prelude). :- lazy([ |on]).
iter(F) = [F|iter(zipWith((+),[0|F],append(F,[0])))].
pas=iter([1]). row(N)=nth(N,pas). comb(N,M)=nth(M,(nth(N,pas))).
row(6) [1, 6, 15, 20, 15, 6, 1]
take(5,pas) [ [1]︸︷︷︸, [1, 1]︸︷︷︸, [1, 2, 1]︸ ︷︷ ︸, [1, 3, 3, 1]︸ ︷︷ ︸, [1, 4, 6, 4, 1]︸ ︷︷ ︸]
↘↓↙¿y si evaluamos las listas internas de modo impaciente?
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Mezclando impaciencia y pereza (I)
Triangulo de Pascal con listas perezosas (Blas et al):
1 row 01 1 row 1
1 2 1 row 21 3 3 1 row 3
1 4 6 4 1 row 4. . .
Idea:
0 1 3 3 1 [0] ++ row 3+ 1 3 3 1 0 row 3 ++ [0]
1 4 6 4 1 row 4
:- include(prelude). :- lazy([ |on]).
iter(F) = [F|iter(zipWith((+),[0|F],append(F,[0])))].
pas=iter([1]). row(N)=nth(N,pas). comb(N,M)=nth(M,(nth(N,pas))).
row(6) [1, 6, 15, 20, 15, 6, 1]
take(5,pas) [ [1]︸︷︷︸, [1, 1]︸︷︷︸, [1, 2, 1]︸ ︷︷ ︸, [1, 3, 3, 1]︸ ︷︷ ︸, [1, 4, 6, 4, 1]︸ ︷︷ ︸]
↘↓↙¿y si evaluamos las listas internas de modo impaciente?
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Mezclando impaciencia y pereza (II)
Para las filas, listas impacientes: row ::= nil | cons (e,row)
Para la lista de filas, listas perezosas: :- lazy([ |on]).
iter2(F)=[F|iter2(zipWithRows((+),cons(0,F),appendRows(F,cons(0,nil))))].
pas2=iter2(cons(1,nil)). row2(N)=... comb2(N,M)=...
Goal Lazy lists Lazy/eager listsrow(400) 0.691386 0.248232
row(600) 1.77859 0.560645
row(800) overflow 1.01706
row(2000) overflow 6.71622
row(4000) overflow 30.0093
comb(500, 250) 0.87144 0.561656
comb(800, 400) 2.13438 2.18744
comb(1000, 500) 5.29124 4.3969
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Metaprogramacion (I)
Cifras y letras: dada una lista de operandos obtener un total conlas operaciones aritmeticas basicas
% expression ::= number | plus exp exp | minus ...
% non deterministic generation of expressions
genExp(Ns)=oneOf(Ns).
genExp(Ns)=E :- split(Ns)=(As,Bs),
E=..[oneOf([plus,minus,mult,div]),genExp(As),genExp(Bs)].
...
% evaluation of expressions
eval(plus(E1,E2)) = ... eval(minus(E1,E2)) = ...
% solution for the count-down problem
sol(V,L)=E :- E=genExp(L), V==eval(E).
Pero, y si queremos la mejor aproximacion?
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Metraprogramacion (II)
Supongamos que tenemos:
best(Gen,Data,Comp)::= devuelve la mejor alternativa dados:
Gen (generador): devuelve pares (Candidato,Valoracion) a partir dela lista de datos Data
Comp: criterio de comparacion para pares (Candidato,Valoracion)
Busqueda de la mejor aproximacion:
bestApprox(V,L) = best(genExpVal,[V,L],better).
genExpVal(V,L) = (E,abs(V-eval(E))) :- genExp(L)=E.
better((E1,V1),(E2,V2)) = (E1,V1) :- V1<V2, !.
better((E1,V1),(E2,V2)) = (E2,V2).
Ej: genExpVal(17,[3,4,1])indet (3 ∗ 4 + 1| {z }
13
, 4|{z}|13−17|
)
bestApprox(26,[4,5,3]) 3*(5+4) (=27)
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Metraprogramacion (II)
Supongamos que tenemos:
best(Gen,Data,Comp)::= devuelve la mejor alternativa dados:
Gen (generador): devuelve pares (Candidato,Valoracion) a partir dela lista de datos Data
Comp: criterio de comparacion para pares (Candidato,Valoracion)
Busqueda de la mejor aproximacion:
bestApprox(V,L) = best(genExpVal,[V,L],better).
genExpVal(V,L) = (E,abs(V-eval(E))) :- genExp(L)=E.
better((E1,V1),(E2,V2)) = (E1,V1) :- V1<V2, !.
better((E1,V1),(E2,V2)) = (E2,V2).
Ej: genExpVal(17,[3,4,1])indet (3 ∗ 4 + 1| {z }
13
, 4|{z}|13−17|
)
bestApprox(26,[4,5,3]) 3*(5+4) (=27)
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Ejemplos. Metaprogramacion (III)
La definicion de best:
best(F,Args,Better) = R :-applyLst(F,Args)=EV, retractall(currentBest( )),assert(currentBest(EV)), !, bestAux(F,Args,Better)=R.
bestAux(F,Args,Better) = R :-applyLst(F,Args)=E, currentBest(C), applyLst(Better,[E,C])=E,retractall(currentBest( )),assert(currentBest(E)), fail.
bestAux( , , )=R:-!,currentBest(R).
applyLst(F,[])=F.
applyLst(F,[X|Xs])=applyLst(F@X,Xs).
best es una funcion generica que encapsula la exploracion delespacio de busqueda
el orden superior facilita el aislamiento de lametaprogramacion del resto del codigo
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Conclusiones y trabajo futuro (I)
El uso de funciones en Prolog enriquece notablemente el lenguajesin perder las capacidades de metaprogramacion propias de Prolog.
La manipulacion explıcita de la pereza mediante anotaciones enconstructoras en vez de funciones resulta muy manejable y efectivaen la practica. Ademas es bastante transparente para elprogramador (el traductor automatiza la gestion de suspensiones).
Requiere un mecanismo automatico de comparticion δ-abstracciones (λ-abstracciones extendidas).
El traductor es relativamente sencillo (unas 500 lıneas de codigo) yde facil manejo.
La traduccion requiere formalizacion, en concreto la generacion yactivacion de suspensiones:
relacion con context sensitive rewriting (S. Lucas, 1998).
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Conclusiones y trabajo futuro (II)
Mejoras del sistema:
Prompt funcional.
X Disponible mediante :- fun. (admite anidamientos yλ-abstracciones, muestra tiempos de ejecucion).
Posibilidad de forzar la evaluacion de expresiones que contienensuspensiones.
X Funcion predefinida nf(Exp)::= evalua Exp a forma normal
Comprobaciones elementales de tipos (chequeo, no inferencia).
46 Actualmente solo comprobaciones simples de aridad.
Optimizaciones de codigo.
46 El sistema analiza el uso de cortes y optimiza el codigoeliminando variables de paso y unificaciones redundantes.
Posibilidad de encapsulado para suspender evaluacion (quotations)
X quot(Exp) λ . Exp
X unquot(Exp) Exp@dummy
J. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach
Conclusiones y trabajo futuro (II)
Mejoras del sistema:
Prompt funcional.
X Disponible mediante :- fun. (admite anidamientos yλ-abstracciones, muestra tiempos de ejecucion).
Posibilidad de forzar la evaluacion de expresiones que contienensuspensiones.
X Funcion predefinida nf(Exp)::= evalua Exp a forma normal
Comprobaciones elementales de tipos (chequeo, no inferencia).
46 Actualmente solo comprobaciones simples de aridad.
Optimizaciones de codigo.
46 El sistema analiza el uso de cortes y optimiza el codigoeliminando variables de paso y unificaciones redundantes.
Posibilidad de encapsulado para suspender evaluacion (quotations)
X quot(Exp) λ . Exp
X unquot(Exp) Exp@dummyJ. Rodrıguez-Hortala, J. Sanchez-Hernandez Lazy Functional Prolog: a Practical Approach