30
Apunte de clase {log} para Ingenier´ ıa de Software Maximiliano Cristi ´ a Licenciatura en Ciencias de la Computaci ´ on Facultad de Ciencias Exactas, Ingenier´ ıa y Agrimensura Universidad Nacional de Rosario Rosario – Argentina c Maximiliano Cristi´ a – 2020 – Todos los derechos reservados

floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

Apunte de clase

{log} para Ingenierıa de Software

Maximiliano Cristia

Licenciatura en Ciencias de la Computacion

Facultad de Ciencias Exactas, Ingenierıa y Agrimensura

Universidad Nacional de Rosario

Rosario – Argentina

c© Maximiliano Cristia – 2020 – Todos los derechos reservados

Page 2: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

Indice

1. Instalacion de {log} 3

2. Traduccion de Z a {log} 32.1. Un ejemplo de traduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.1.1. La especificacion Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.1.2. El codigo {log} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.2. Otra forma de codificar las variables de estado . . . . . . . . . . . . . . . . . . . . . . . 82.3. Traduccion de pares ordenados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.4. Traduccion de conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.4.1. Conjuntos extensionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.4.2. Producto cartesiano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.4.3. Intervalos de numeros enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.5. Traduccion de la aplicacion de funcion . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.6. Traduccion de tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.6.1. Tipos enumerados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.6.2. Los conjuntos de numeros enteros y naturales . . . . . . . . . . . . . . . . . . . 122.6.3. Dominio y codominio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.7. Traduccion de expresiones aritmeticas . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.8. Traduccion de los operadores de la teorıa de conjuntos . . . . . . . . . . . . . . . . . . 142.9. Traduccion de operadores logicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.9.1. Cuantificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.10. Traduccion de definiciones axiomaticas . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3. Simulacion de prototipos {log} 183.1. Simulaciones simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.2. Simulaciones simbolicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.3. Simulaciones inversas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.4. Evaluacion de propiedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

4. Pruebas con {log} 26

A. Codigo {log} de la agenda de cumpleanos 29

Page 3: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

3

1. Instalacion de {log}

{log} (‘setlog’) es un lenguaje de programacion basado en el paradigma de programacion logica derestricciones, pero ademas es un satisfiability solver y un demostrador automatico de teoremas. Una delas caracterısticas distintivas de {log} es que los conjuntos son entidades de primer nivel (es decir sonparte integral del lenguaje).

El desarrollo de {log} lo comenzo Gianfranco Rossi en Italia a mediados de los anos 90 junto avarios estudiantes de doctorado y colegas. Desde 2012 Gianfranco Rossi y Maximiliano Cristia trabajanjuntos en la extension de {log} a relaciones binarias y otras teorıas relacionadas.

{log} esta implementado en Prolog. Por lo tanto para poder usar {log} primero hay que instalarun interprete de Prolog. Si bien en principio {log} puede ejecutar sobre cualquier interprete Prolog, elinterprete sobre el cual esta testeado es SWI-Prolog (http://www.swi-prolog.org). Luego se de-be copiar en cualquier directorio el contenido de http://www.fceia.unr.edu.ar/is2/tp/setlog.tar.gz.

2. Traduccion de Z a {log}

Como la mayorıa de las especificaciones Z tienen una estructura muy similar, comenzaremos mos-trando como traducir una tıpica especificacion Z a {log} por medio de un ejemplo. Luego explicaremoscon cierto detalle como traducir los elementos de Z que no aparecen en el ejemplo o que se puedentraducir de mas de una forma.

2.1. Un ejemplo de traduccion

La especificacion que usaremos como ejemplo es una de las especificaciones usadas por Spivey envarios de sus artıculos y libros [2], conocida como la agenda de cumpleanos (birthday book, en ingles).

2.1.1. La especificacion Z

Comenzamos dando algunas designaciones.

n es un nombre ≈ n ∈ NAME

d es una fecha ≈ d ∈ DATE

k es el nombre de una persona cuyo cumpleanos hay registrar ≈ k ∈ known

La fecha de cumpleanos de la persona k ≈ birthday k

Entonces introducimos los siguientes tipos basicos.

[NAME,DATE]

Ahora podemos definir el espacio de estados de la especificacion de la siguiente forma.

BirthdayBookknown : PNAMEbirthday : NAME 7→ DATE

Page 4: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

4

El estado inicial de la agenda de cumpleanos es el siguiente.

BirthdayBookInitBirthdayBook

known = /0birthday = /0

El siguiente esquema describe los predicados que deberıan ser invariantes de estado.

BirthdayBookInvBirthdayBook

known = dombirthday

La primera operacion que modelamos es como agregar una fecha de cumpleanos a la agenda. Comosiempre modelamos primero el caso exitoso, luego los errores y finalmente integramos todo en una unicaexpresion de esquemas.

AddBirthdayOk∆BirthdayBookname? : NAMEdate? : DATE

name? /∈ knownknown′ = known∪{name?}birthday′ = birthday∪{name? 7→ date?}

NameAlreadyExistsΞBirthdayBookname? : NAME

name? ∈ known

AddBirthday == AddBirthdayOk ∨ NameAlreadyExists

La segunda operacion a especificar corresponde a mostrar el cumpleanos de una persona dada.

FindBirthdayOkΞBirthdayBookname? : NAMEdate! : DATE

name? ∈ knowndate! = birthday(name?)

Page 5: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

5

NotAFriendΞBirthdayBookname? : NAME

name? /∈ known

FindBirthday == FindBirthdayOk ∨ NotAFriend

Finalmente tenemos una operacion que nos lista los nombres de las personas cuya fecha de cum-pleanos es hoy.

RemindΞBirthdayBooktoday? : DATEcards! : PNAME

cards! = dom(birthdayB{today?})

2.1.2. El codigo {log}

El codigo {log} de la traduccion de la especificacion Z se debe guardar en un archivo con extension.pl preferentemente en el mismo directorio donde fue instalado {log}.

La mayorıa de los esquemas Z se traducen a clausulas {log}. Una clausula {log} es algo ası como unprocedimiento o subrutina. Cada clausula puede recibir cero o mas parametros. Cuando se traduce un es-quema Z que representa una operacion del sistema, los parametros que recibe la clausula correspondienteseran las variables de estado, las de entrada y las de salida.

En {log} las variables siempre deben empezar con una letra mayuscula o el caracter de subrayado(_), aunque este en general queda reservado para casos especiales. Cualquier identificador que comienzacon una letra minuscula es una constante.

En {log} el caracter prima (′) no se puede usar como parte del nombre de una variable. Por lo tantopara identificar las variables de estado posterior pondremos el caracter de subrayado al final. Por lotanto, por ejemplo, las variables de estado de la especificacion de la agenda de cumpleanos seran Known

y Birthday; y las de estado posterior Known_ y Birthday_.De igual forma, las decoraciones ? y ! no pueden formar parte de los nombres de variables {log}. En

este caso usaremos los sufijos _i y _o para identificar facilmente las variables de entrada (input) y salida(output), respectivamente.

De esta forma, la interfaz de la clausula {log} correspondiente a la operacion Z AddBirthday es lasiguiente:

addBirthday(Known,Birthday,Name_i,Date_i,Known_,Birthday_)

donde Name_i y Date_i corresponden a las variables de entrada name? y date? declaradas en AddBirthday.Notar que si bien AddBirthday comienza con mayuscula addBirthday lo hace con minuscula porquelas clausulas {log} deben comenzar de esa forma; por otro lado, si bien name? y date? comienzan conminuscula, Name_i y Date_i lo hacen con mayuscula porque los parametros variables de las clausulasdebe comenzar de esa forma. Por otro lado, Known y Birthday representan el estado de partida mientrasque Known_ y Birthday_ representan el estado de llegada.

Ahora podemos dar la definicion de la clausula addBirthday:

Page 6: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

6

addBirthday(Known,Birthday,Name_i,Date_i,Known_,Birthday_) :-

addBirthdayOk(Known,Birthday,Name_i,Date_i,Known_,Birthday_)

or

nameAlreadyExists(Known,Birthday,Name_i,Known_,Birthday_).

donde or equivale a la disyuncion logica. Observar que a nameAlreadyExists no se le pasa el parame-tro Date_i porque no se declara en NameAlreadyExists; ademas la clausula termina con un punto.

A su vez la definicion de addBirthdayOk es la siguiente:

addBirthdayOk(Known,Birthday,Name_i,Date_i,Known_,Birthday_) :-

Name_i nin Known &

un(Known,{Name_i},Known_) &

un(Birthday,{[Name_i,Date_i]},Birthday_).

donde:

El sımbolo & corresponde a la conjuncion.

nin corresponde al operador /∈. Es decir, Name_i nin Known significa Name i /∈ Known.

un(Known,{Name_i},Known_) significa Known = Known∪{Name i}.

Es importante notar que no hemos indicado los tipos de las variables. En realidad {log} es un forma-lismo no tipado. De todas formas la nocion de “variable de tipo T” se puede traducir como la pertenenciade esa variable a un conjunto T . Por otro lado, en general {log} es capaz de determinar el “tipo” de cadavariable de acuerdo a la forma en que es usada. Por ejemplo, al escribir algo como x - 1, {log} sabraque el “tipo” de x son los enteros; y si en algun otro lado decimos x >= 0, estarıamos diciendo queel “tipo” de x son los naturales. Por defecto, {log} asume que las variables son de “tipo” conjunto (esdecir, por defecto cualquier variable es un conjunto), hasta el momento en que puede precisar mejor el“tipo”. Como en Z, en {log} las relaciones binarias, las funciones parciales y las listas son conjuntos.Sin embargo, estos conjuntos son no tipados. O sea {a,1,[X,2],{Y,Z}} es un conjunto {log} (dondea es una constante, X, Y y Z son variables, y [X,2] es el par ordenado (X,2)).

Entonces, ¿por que no especificamos los tipos de las variables en addBirthday? Mas concretamente,¿por que no dimos el tipo de Name_i?. En la especificacion Z, el tipo de name? es NAME y este es untipo basico. En {log} podrıamos haber dicho Name_i in NAME (donde in corresponde a ∈), pero parael uso que vamos a hacer de {log} no vale la pena si asumimos que hemos chequeado los tipos de laespecificacion Z. Como en Z, en {log} NAME es un conjunto del cual desconocemos sus elementos, nosabemos que forma tienen; y como son conjuntos no tipados podemos poner cualquier cosa que nosconvenga. {log} no se quejarıa si escribieramos, por ejemplo, Name_i = Date_i lo cual, desde el puntode vista de Z, serıa un error (de tipos). Pero como nosotros estamos traduciendo una especificacion Z queha pasado el control de tipos, esta igualdad jamas aparecera.

Entonces, ¿no hay que especificar el tipo de ninguna variable? En algunos casos tenemos que es-pecificar los tipos. En general, esto se da cuando en Z la declaracion de la variable no esta norma-lizada. Por ejemplo, x : N es una declaracion no normalizada porque N no es un tipo (es un conjun-to). La declaracion normalizada serıa x : Z mas x ≥ 0 en la parte de predicados, en cuyo caso {log}deducirıa el “tipo” de x por el predicado x ≥ 0. En el ejemplo de la agenda de cumpleanos la decla-racion birthday : NAME 7→ DATE no esta normalizada. La declaracion normalizada serıa birthday :NAME ↔ DATE mas birthday ∈ NAME 7→ DATE en la parte de predicados. En este caso se podrıatraducir birthday ∈ NAME 7→ DATE como pfun(Birthday), donde pfun es un operador {log} queimplementa la definicion de funcion (parcial) como una subclase de los conjuntos de pares ordenados.

Page 7: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

7

Notar que no hace falta decir que Birthday es una relacion binaria porque ya estamos diciendo que esuna funcion parcial (las cuales son relaciones binarias). Por otro lado, como NAME y DATE son tiposbasicos en general no vale la pena decir que el dominio de Birthday es un subconjunto de NAME (ylo mismo para el rango). Pero entonces, ¿por que no dijimos pfun(B) en algun lado de addBirthday?Porque la idea es usar {log} para demostrar que pfun(B) es un invariante de estado de la especificacion.De hecho si hubieramos escrito el esquema BirthdayBook con declaraciones normalizadas resultarıa losiguiente:

BirthdayBookknown : PNAMEbirthday : NAME↔ DATE

birthday ∈ NAME 7→ DATE

donde birthday∈NAME 7→DATE serıa un invariante de estado por definicion. Por otro lado, segun vimosen Ingenierıa de Software I [1], nosotros no usamos invariantes por definicion sino que los escribimos enel esquema BirthdayBookInv. En consecuencia tendrıamos:

BirthdayBookknown : PNAMEbirthday : NAME↔ DATE

BirthdayBookInvBirthdayBook

known = dombirthdaybirthday ∈ NAME 7→ DATE

donde es claro que deberıamos demostrar que pfun(Birthday) es un invariante de estado de la especi-ficacion. Esto lo veremos con mas detalle en la Seccion 4.

Ahora continuamos con la traduccion de la especificacion. Veamos la definicion de nameAlready

Exists:

nameAlreadyExists(Known,Birthday,Name_i,Known_,Birthday_) :-

Name_i in Known &

Known_ = Known &

Birthday_ = Birthday.

donde podemos ver como se indica que no hay cambio de estado.Notar que el orden en que se definen las clausulas es irrelevante en el sentido en que una clausula

puede definirse luego o antes de haber sido invocada por primera vez.El segundo esquema de operacion a traducir es FindBirthday.

findBirthday(Known,Birthday,Name_i,Date_o,Known_,Birthday_) :-

findBirthdayOk(Known,Birthday,Name_i,Date_o,Known_,Birthday_)

or

notAFriend(Known,Birthday,Name_i,Known_,Birthday_).

Page 8: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

8

donde podemos empezar a ver que la traduccion comienza a ser repetitiva. A continuacion mostramoslas definiciones de findBirthdayOk y notAFriend:

findBirthdayOk(Known,Birthday,Name_i,Date_o,Known_,Birthday_) :-

Name_i in Known &

apply(Birthday,Name_i,Date_o) &

Known_ = Known &

Birthday_ = Birthday.

notAFriend(Known,Birthday,Name_i,Known_,Birthday_) :-

Name_i nin Known &

Known_ = Known &

Birthday_ = Birthday.

donde podemos ver el uso de variables de salida y el uso del predicado {log} apply que implementa laaplicacion de una funcion a su argumento. Es decir, apply(F,X,Y) es verdadero si y solo si F(X) = Ylo es. Observar que la aplicacion tiene sentido solo si F es una funcion y no cualquier conjunto. {log}garantiza esto pues internamente apply “tipa” a su primer argumento con el predicado pfun(F). Por lotanto si apply llegara a ser invocado con un primer argumento que no fuera una funcion, el predicadofallarıa haciendo que {log} responda no.

Finalmente la traduccion de la operacion Remind es la siguiente:

remind(Known,Birthday,Today_i,Cards_o,Known_,Birthday_) :-

rres(Birthday,{Today_i},M) &

dom(M,Cards_o) &

Known_ = Known &

Birthday_ = Birthday.

Este ejemplo es interesante porque podemos ver como se deben traducir las expresiones Z que involu-cran varios operadores de la teorıa de conjuntos y relaciones. En efecto, como en {log} los operadoresde la teorıa de conjuntos se implementan como predicados, no es posible escribir expresiones. Lo quese debe hacer es introducir variables nuevas (como M) para “encadenar” los predicados. El predicadorres(R,A,S) equivale a S = RBA en tanto que dom(R,B) equivale a domR = B (es decir dom(R,B)permite calcular el dominio de R y “guardarlo” en B).

El estado inicial se traduce como una clausula que solo recibe un registro con las variables de estado:

birthdayBookInit(Known,Birthday) :-

Known = {} &

Birthday = {}.

donde {} es la forma de escribir el conjunto vacıo ( /0).La traduccion del esquema con los invariantes de estado (BirthdayBookInv) la veremos en la seccion

4.En el Apendice A pueden encontrar todo el codigo {log} de este ejemplo.

2.2. Otra forma de codificar las variables de estado

El esquema de estado de la agenda de cumpleanos tiene dos variables. Esas variables se incluyecomo parametros de las clausulas que codifican las operaciones de la especificacion; ademas hay queagregar las variables de estado siguiente (las que terminan con ‘_’). Esto puede volverse complicado si la

Page 9: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

9

operacion Z tiene muchas variables de estado. En ese caso habrıa que definir clausulas {log} con muchosparametros lo que podrıa no ser facil de leer.

Una forma alternativa de codificar las variables de estado es empaquetandolas en una lista Prolog yluego usar unificacion de listas Prolog para acceder a las variables. El siguiente codigo {log} usa estacodificacion en la operacion addBirthdayOk:

addBirthdayOk(BirthdayBook,Name_i,Date_i,BirthdayBook_) :-

BirthdayBook = [Known,Birthday] &

Name_i nin Known &

un(Known,{Name_i},Known_) &

un(Birthday,{[Name_i,Date_i]},Birthday_) &

BirthdayBook_ = [Known_,Birthday_].

donde BirthdayBook representa el estado de partida y BirthdayBook_ el de llegada. Se supone queambos son listas de dos elementos. Esa suposicion se fuerza con las igualdades:

BirthdayBook = [Known,Birthday]

BirthdayBook_ = [Known_,Birthday_]

Esto significa que si por algun motivo se invoca addBirthdayOk con un primer parametro que no unificacon [Known,Birthday], la invocacion fallara (lo mismo para el ultimo parametro).

Observar como se establece el estado posterior unificando BirthdayBook_ con la lista [Known_,

Birthday_] la cual contiene las variables que fueron usadas en el predicado de la operacion para cap-turar los resultados de las dos uniones.

Se puede unificar BirthdayBook con una lista que contenga dos variables cualesquiera; no tienenpor que tener los mismos nombres que en la especificacion. Por ejemplo, BirthdayBook = [K,B].

Notar que el primer y ultimo parametros de addBirthdayOk llevan el nombre del esquema de estadode la especificacion Z. Esta convencion ayuda a relacionar el codigo {log} con la especificacion Z, perono es de ninguna manera obligatoria.

Claramente, esta forma alternativa de codificar las variables de estado traslada la complejidad delnumero de parametros de la clausula al numero de elementos de la lista de variables. Por lo tanto quedaa criterio del programador cual de las dos codificaciones es la mas conveniente. De hecho ambas codifi-caciones pueden coexistir en el mismo programa {log}. Obviamente en ese caso se debe ser cuidadosocuando se invocan las diversas clausulas.

Una leve ventaja que tiene la codificacion de las variables de estado usando listas se aprecia en lasoperaciones que no usan algunas de las variables de estado. Por ejemplo, la operacion Z Remind no usala variable de estado known. En ese caso se la puede codificar de la siguiente forma:

remind(BirthdayBook,Today_i,Cards_o,BirthdayBook_) :-

BirthdayBook = [_,B] &

rres(B,{Today_i},M) &

dom(M,Cards_o) &

BirthdayBook_ = BirthdayBook.

donde hemos puesto un ‘_’ como primer elemento de la lista con la cual se unifica BirthdayBook. Estosignifica que no importa ese elemento de la lista. Si la lista tiene muchos elementos y muchos de ellosno se usan en una clausula, se puede usar el ‘_’ en distintas posiciones de la lista.

Otra ventaja de usar listas es que resulta muy facil establecer que no hay cambio de estado. Por ejem-plo, en la agenda de cumpleanos solo hay que escribir BirthdayBook_ = BirthdayBook en lugar de

Page 10: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

10

Known_ = Known & Birthday_ = Birthday. Cuando hay muchas variables de estado esta codifica-cion resulta muy conveniente.

Naturalmente, si la lista es muy larga es un problema recordar que variable hemos puesto en cadaposicion. Hay que ser muy cuidadoso para evitar cambiar el orden de las variables porque hara que elprograma {log} sea inconsistente.

2.3. Traduccion de pares ordenados

Los pares ordenados se traducen a {log} como listas Prolog de dos elementos. Por ejemplo si x esuna variable (x,3) se traduce como [X,3].

Si en Z tenemos algo de la forma p : Z× V y p.1 = x− 4 lo traducimos de la siguiente forma:P = [A,_] & A is X - 4 (ver el operador is en la Seccion 2.7). Es decir que, basicamente, usamosunificacion para forzar que P sea una lista de dos elementos tal que el primero es la variable A la cual asu vez se pide que sea igual a X - 4. A debe ser una variable no usada en la clausula. Notar que usamos‘_’ porque no nos interesa el segundo parametro de P.

Las listas Prolog no deben usarse para otras cosas que las que hemos indicado aquı. En general unprograma {log} que usa listas Prolog de otras formas suele perder propiedades importantes.

2.4. Traduccion de conjuntos

2.4.1. Conjuntos extensionales

El conjunto {1,2,3} se traduce simplemente como {1,2,3}. Si uno de los elementos del conjuntoes una variable o una constante de un tipo enumerado, hay que tener en cuenta las diferencias que hayentre Z y {log} en cuanto a constantes y variables. Por ejemplo, si en Z x es una variable, entonces elconjunto {2,x,6} se traduce como {2,X,6}.{log} provee una forma de definir conjuntos por extension que, en un sentido, es mas poderosa que lo

que ofrece Z. Por ejemplo, el siguiente esquema lo vimos cuando estudiamos Z en Ingenierıa de SoftwareI [1]:

CerrarCajaOk∆Bancod? : DNIrep! : MENSAJES

d? ∈ domcaca d? = 0ca′ = {d?}−C carep! = ok

Usando una traduccion directa de CerrarCajaOk obtendrıamos lo siguiente:

cerrarCajaOk(Ca,D_i,Rep_o,Ca_) :-

dom(Ca,D) &

D_i in D &

apply(Ca,D_i,0) &

dares({D_i},Ca,Ca_).

Page 11: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

11

Este codigo {log} no esta mal pero existe una alternativa mejor (en lo que a {log} se refiere) basada enel concepto de unificacion conjuntista. El codigo {log} usando unificacion conjuntista es el siguiente:

cerrarCajaOk(Ca,D_i,Rep_o,Ca_) :-

Ca = {[D_i,0] / Ca_} & [D_i,0] nin Ca_.

Es decir el predicado Ca = {[D_i,0] / Ca_} unifica Ca con {[D_i,0] / Ca_} de forma tal queencuentra valores para las variables que hagan que la igualdad sea verdadera. Si tales valores no existen,la unificacion falla y {log} responde no. Si t es un valor para Ca_ que satisface la unificacion entonces{[D_i,0] / t} tambien lo es, pues en ese caso tenemos

Ca = {[D_i,0] / t} = {[D_i,0],[D_i,0] / t} = {[D_i,0] / {[D_i,0] / t}}

De aquı que en cerrarCajaOk se agregue el predicado [D_i,0] nin Ca_ puesto que de esta forma seevita la solucion anterior que no serıa correcta en relacion a la especificacion CerrarCajaOk.

El termino {.../...} se llama constructor de conjuntos extensionales. En {E/C} el segundo parame-tro (i.e. C) debe ser un conjunto. La interpretacion de {E/C} es {E}∪C por lo que es posible una soluciondonde E ∈ C. Si tal solucion no es correcta o necesaria se debe conjugar el predicado E /∈ C de formaexplıcita; en general es conveniente agregar ese predicado. Para simplificar la entrada/salida, {log} aceptae imprime terminos como {1,2 / X} en lugar de {1 / {2 / X}}.

Si bien ambas versiones de cerrarCajaOk son equivalentes, en general, {log} sera mas eficientecon la segunda que con la primera.

2.4.2. Producto cartesiano

Otra forma de construir un conjunto es mediante el producto cartesiano de dos conjuntos: cp(A,B),donde A y B pueden ser cualesquiera conjuntos extensionales, es equivalente a A×B.

2.4.3. Intervalos de numeros enteros

Un intervalo Z de la forma n . .m se traduce como int(n,m) teniendo en cuenta las diferencias entrevariables y constantes que existen en {log}.

2.5. Traduccion de la aplicacion de funcion

En {log} un predicado de la forma X in A es inmediatamente transformado en el predicado:

A = {X / B} & X nin B

donde B es una variable cuantificada existencialmente (que {log} crea automaticamente). O sea que unpredicado de pertenencia se transforma en una unificacion de conjuntos.

Una de las aplicaciones interesantes de la unificacion conjuntista es la aplicacion de una funcion a suargumento. Dado que en Z la mayor parte de las funciones que se usan en especificaciones son parcialeses necesario agregar predidcados de la forma x ∈ dom f , antes de aplicar f a x. La traduccion a {log} deestas formulas puede hacerse de forma directa o usando convenientemente un predicado de pertenenciaque da lugar a una unificacion conjuntista. Por ejemplo, la formula Z:

x ∈ dom f ∧ f x = h

puede traducirse de forma directa:

Page 12: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

12

dom(F,D) & X in D & apply(F,X,H)

o usando unificacion conjuntista:[X,H] in F & pfun(F)

lo que es equivalente y mucho mas eficiente pues no requiere “calcular” el dominio de F. En relacion ala equivalencia entre ambas formulas, notar que [X,H] in F se transforma en F = {[X,H] / G} (paraalgun G) por lo que si en F no hay ningun par ordenado cuya primera componente sea X la unificacionfallara lo que es equivalente a que x∈ dom f sea falso. De igual forma si en F el par ordenado cuya primeracomponente es X tiene como segunda componente algo que no es H, la unificacion tambien fallara (lo quees equivalente a f x 6= h).

2.6. Traduccion de tipos

En general no es necesario indicar los tipos de las variables Z cuando son traducidas a {log}. Sinembargo, existen algunas excepciones que mencionamos a continuacion.

2.6.1. Tipos enumerados

Los tipos enumerados de Z se puede traducir de forma muy simple como conjuntos extensionales.De esta forma el tipo:

T ::= c1 | . . . | cn

se puede traducir como:T = {c1,...,cn}

teniendo en cuenta que c1,...,cn deben ser todas constantes. Es decir que si alguna de las ci es unapalabra que comienza con mayuscula, se la debe traducir comenzando con minuscula. Si esto producealgun conflicto con otro identificador se lo debe resolver mediante alguna convencion. Por ejemplo eltipo Z:

Saludo ::= hola | Hola

declara dos valores diferentes pero que al ser traducidos a {log} se convierten en el mismo valor puesHola debe ser traducido como hola ya que no puede comenzar con mayuscula (pues en ese caso serıauna variable). El conflicto se puede resolver anteponiendo una letra cualquiera a cada valor del tipo:c_hola y c_Hola.

2.6.2. Los conjuntos de numeros enteros y naturales

El tipo de los numeros enteros de Z (i.e. Z) no es necesario traducirlo porque {log} infiere el tipo apartir de las expresiones donde se usan las variables que deberıan tener ese tipo.

Como el conjunto de los numeros naturales (N) no es un tipo es necesario indicar que una variabletoma valores en N mediante la restriccion x >= 0. Para indicar que el conjunto A es un subconjunto delos naturales se debe hacer mediante una cuantificacion universal restringida:foreach(X in A, 0 =< X)

De todas formas, en muchas situaciones, esta restriccion corresponde mas un invariante que a untipo. Si es un invariante se deberıa probar que efectivamente lo es y no establecer por definicion quelo es (recordar la diferencia entre invariantes por definicion y por demostracion vista en Ingenierıa deSoftware I [1]).

Page 13: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

13

2.6.3. Dominio y codominio

Normalmente no es necesario indicar el tipo del dominio y codominio de una relacion binaria (y deuna funcion). Sin embargo cuando la declaracion Z de la relacion binaria no esta normalizada o cuandointervienen tipos enumerados, es necesario indicar el tipo del dominio y codominio.

Si U es un tipo enumerado y T esta normalizado, la declaracion:

S : T↔ U

corresponde al siguiente codigo {log}:ran(S,_N) & subset(_N,[|U|])

donde _N es una variable nueva, [|U|] denota la traduccion de U y ran implementa el rango de unarelacion binaria. Notar que no decimos que S es una relacion binaria dado que {log} infiere que S es unarelacion binaria por ser el primer argumento del operador ran.

Si T esta normalizada, la declaracion:

S : m . .n↔ T

se traduce como:

dom(S,_N) & subset(_N,int(M,N))

donde _N es una variable nueva y dom implementa el dominio de una relacion binaria.Finalmente, si T esta normalizada una declaracion como:

S : N↔ T

se traduce como sigue:

dom(S,_N) & foreach(X in _N,0 =< X)

donde _N y X son variables nuevas (ver el predicado foreach en la Seccion 2.9). No podemos decirsubset(_N,int(0,A)), para algun A, como hicimos antes porque no sabemos cual es el maximo delintervalo.

2.7. Traduccion de expresiones aritmeticas

En general las expresiones aritmeticas de Z se traducen de forma directa a {log}, aunque hay algunasexcepciones. Los sımbolos ≤ y ≥ se traducen como =< y >=, respectivamente. El operador 6= se traducecomo neq.

Una igualdad de la forma x′ = x+1 se traduce como X_ is X + 1 (es decir, en igualdades aritmeti-cas, no hay que usar = sino is). Mas aun, si en Z tenemos A = {x,y− 4} (A, x e y variables) tenemosque traducirlo como: A = {X,Z} & Z is Y - 4, donde Z debe ser una variable no usada en la clausu-la. El problema es que ni {log} ni Prolog evaluan expresiones aritmeticas a menos que el programa-dor lo pida usando el operador is. Es decir si en {log} ejecutamos {X,Y - 4} = {Y - 3 - 1,X},la respuesta sera no porque {log} intentara determinar si Y - 4 = Y - 3 - 1 sin evaluar ambas ex-presiones (es decir las considerara, basicamente, como cadenas de caracteres donde Y es una variableentera y por lo tanto la igualdad es imposible sin importar el valor de Y). Por el contrario, si ejecuta-mos {X,A} = {B,X} & A is Y - 4 & B is Y - 3 - 1 {log} retornara varias soluciones (algunasde ellas repetidas), lo que significa que los conjuntos son iguales de varias formas posibles.

Page 14: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

14

OPERADOR {log} SIGNIFICADO

conjunto set(A) A es un conjuntoigualdad A = B A = Bpertenencia x in A x ∈ Aunion un(A,B,C) C = A∪Binterseccion inters(A,B,C) C = A∩Bdiferencia diff(A,B,C) C = A\Bsubconjunto subset(A,B) A⊆ Bsubconjunto estricto ssubset(A,B) A⊂ Bconjuntos disyuntos disj(A,B) A ‖ Bcardinalidad size(A,n) |A|= n

NEGACIONES

igualdad A neq B A 6= Bpertenencia x nin A x /∈ Aunion nun(A,B,C) C 6= A∪Binterseccion ninters(A,B,C) C 6= A∩Bdiferencia ndiff(A,B,C) C 6= A\Bsubconjunto nsubset(A,B) A 6⊆ Bconjuntos disyuntos ndisj(A,B) A 6‖ B

Cuadro 1: Operadores de la teorıa de conjuntos disponibles en {log}

2.8. Traduccion de los operadores de la teorıa de conjuntos

Los operadores de la teorıa de conjuntos (incluyendo relaciones binarias, funciones parciales y se-cuencias) se traducen segun lo muestran las Tablas 1, 2 y 3.

Para poder trabajar con los operadores de secuencias de la Tabla 3 es necesario cargar el archivolist.pl (i.e. consult(’list.pl’)), el cual es parte del archivo http://www.fceia.unr.edu.ar/

is2/setlog.tar.gz.El operador de cardinalidad solo acepta una variable o una constante como segundo argumento. Es

decir que si ejecutamos size(A,X + 1) {log} responde no; en cambio si ejecutamos size(A,Y) &

Y is X + 1 (Y debe ser una variable no usada en la clausula) la respuesta es true porque la formula essatisfacible. {log} tambien respondera no si ejecutamos size(A,Y) & Y = X + 1.

2.9. Traduccion de operadores logicos

En {log} solo existen los conectores logicos equivalentes a la conjuncion (&) y a la disyuncion (or).La negacion logica (¬ ) no existe en {log} porque, en un sentido, no es necesaria. En efecto, por caso, siqueremos traducir ¬ x ∈ A lo podemos hacer como1 x nin A. De igual forma, ¬ A = b se traduce comoA neq b. En general, para cada operador de conjuntos y relacional existe un predicado que implementasu negacion. Por ejemplo, la formula Z A 6⊆ B se traduce como nsubset(A,B). Las Tablas 1 y 2 incluyenlas negaciones de todos los predicados de la teorıa de conjuntos.

En resumen un esquema Z como el que sigue:

1Siempre teniendo en cuenta la forma de traducir variables, constantes y expresiones.

Page 15: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

15

OPERADOR {log} SIGNIFICADO

relacion binaria rel(R) R es una relacion binariafuncion parcial pfun(R) R es una funcion parcialaplicacion de funcion apply(f,x,y) f (x) = ydominio dom(R,A) domR = Arango ran(R,A) ranR = Acomposicion comp(R,S,T) T = R◦Sinversa inv(R,S) S = R−1

restriccion de dominio dres(A,R,S) S = ACRanti-restriccion de dominio dares(A,R,S) S = A−CRrestriccion de rango rres(A,R,S) S = RBAanti-restriccion de rango rares(A,R,S) S = R−BAactualizacion oplus(R,S,T) T = R⊕Simagen relacional rimg(R,A,B) B = R[A]

NEGACIONES

Todas las negaciones se escriben anteponiendo una letra n al operador correspondiente. Por ejemplola negacion de dom(R,A) es ndom(R,A), la de dares(A,R,S) es ndares(A,R,S), etc.

Cuadro 2: Operadores relacionales disponibles en {log}

OPERADOR {log} SIGNIFICADO

lista slist(s) s es una listalista extensional {[1,a],[2,b],...,[n,z]} 〈a,b, . . . ,z〉cabecera head(s,e) e = head scola tail(s,t) t = tail sultimo last(s,e) e = last sfrente front(s,t) t = front sagregar (cons) add(s,e,t) t = sa 〈e〉concatenacion concat(s,t,u) u = sa tfiltrado filter(A,s,t) t = A � sextraccion extract(s,A,t) t = s � A

Cuadro 3: Operadores de listas disponibles en {log}

Page 16: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

16

ExtraerE1ΞCABancod? : DNIm? : DINEROrep! : MENS

¬ (d? ∈ domca ∧ m?≤ ca d? ∧ m? > 0)rep! = error1

se lo puede traducir de la siguiente forma (asumimos que el esquema CABanco declara solo la variableca):extraerE1(Ca,D_i,M_i,Rep_o,Ca_) :-

(dom(Ca,D) &

D_i nin D

or

apply(Ca,D_i,Y) &

M_i > Y

or

M_i =< 0

) &

Rep_o = error1 &

Ca_ = Ca.

Los restantes conectores logicos proposicionales se deben traducir usando las equivalencias propo-sicionales en terminos de ∧, ∨ y ¬ . Por ejemplo p⇒ q primero se escribe como ¬ p ∨ q y luego setraducen ¬ p y q.

2.9.1. Cuantificadores

En general el cuantificador existencial no es necesario escribirlo de forma explıcita porque la semanti-ca de los programas {log} es una cuantificacion existencial. Por ejemplo si en Z tenemos:

∃x : N | x ∈ A

lo traducimos simplemente como:0 =< X & X in A

porque la semantica del predicado {log} es, esencialmente, una cuantificacion existencial.La cosa cambia cuando se trata de cuantificadores universales. En {log} solo existen los cuantifica-

dores universales restringidos (RUQ). Un RUQ es una formula de la forma:

∀x ∈ A : P(x)

donde P es una proposicion que depende de x. En {log} los RUQ se codifican de la siguiente forma:foreach(X in A,P(X))

aunque hay formas mas complejas y expresivas2.Recuerden que un uso apropiado del lenguaje Z reduce al mınimo la necesidad de formulas cuantifi-

cadas.2Los RUQ en {log} son mas o menos complejos ası que si necesitan usarlos pidan ayuda al docente.

Page 17: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

17

2.10. Traduccion de definiciones axiomaticas

No existe una forma estandar y unica de traducir las definiciones axiomaticas de Z pues estas sonmuy generales y sirven para multiples propositos. Por este motivo mostraremos como traducir las formasmas habituales de definiciones axiomaticas.

Uno de los problemas al traducir definiciones axiomaticas es que son objetos globales de una espe-cificacion Z y {log} no provee un mecanismo simple para definir y usar objetos globales.

La forma mas general de traducir definiciones axiomaticas es definiendo una clausula {log} queincluye los predicados de la definicion axiomatica. Como siempre se deben tener en cuenta las diferenciasentre variables y constantes y los casos donde se deben traducir los tipos.

Veamos algunos casos tıpicos.

Especificacion Z.

root : USR

Codigo {log}.root_da(X) :- X = root.

Especificacion Z.

adm : PUSR

adm = {root,sec}

Codigo {log}.adm_da(X) :- X = {root,sec}.

Como muestra el siguiente ejemplo algunas definiciones axiomaticas requieren definiciones recursi-vas.

Especificacion Z.

sum : seqZ→ Z

sum 〈〉= 0∀s : seqZ; n : Z• sum(sa 〈n〉) = n+ sum s

Codigo {log}. Asumimos que la lista es un conjunto de pares.sum_da({},0).

sum_da({[N,X]/S},Sum) :-

[N,X] nin S & Sum is X + Sum1 & sum_da(S,Sum1).

Finalmente, las clausulas que corresponden a definiciones axiomaticas se usan desde las clausulasque definen las operaciones. Por ejemplo, la siguiente es una version simplificada de la operacion que lepermite al usuario a crear la cuenta del usuario u:crearUsr(...,A,U,...) :- ... & root_da(A) & ...

o sea que estamos chequeando que A sea root. La siguiente version chequea que A sea un administrador:crearUsr(...,A,U,...) :- ... & adm_da(Adm) & A in Adm...

Lo que ocurre en estos casos es que la variable A unifica con la variable X (que es el parametro formal delas definiciones de root_da y adm_da) lo que implica que, en el primer caso, vale que A es igual a rooty, en el segundo, vale que A es igual a {root,sec}.

Page 18: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

18

3. Simulacion de prototipos {log}

Cuando una especificacion Z se traduce a un programa {log}, lo que tenemos, desde cierto punto devista, es un prototipo del sistema que queremos implementar. Efectivamente, un programa {log} es eso,un programa, pero es un programa que se obtiene de manera casi directa a partir de una especificacionZ3. Ademas es un programa que en general no satisfara los requisitos de desempeno de un programade produccion por lo que es en realidad un prototipo del programa final. El punto es que {log} permiteobtener un prototipo casi sin tener que trabajar extra, solo es necesario escribir la especificacion y luegotraducirla. Esto permitirıa validar tempranamente los requerimientos con el usuario final.

Validar los requerimientos significa poder ejecutar el prototipo junto al usuario para que este puedaobservar las salidas y efectos producidos por el prototipo, y ası determinar si cumple con sus expectativaso no. Si bien los prototipos con los que trabajaremos en esta actividad no son los ideales, sirven comopara dar una idea de la potencialidad de la combinacion entre Z y {log}.

Dado que vemos a los programas {log} como prototipos hablamos mas de simulaciones o anima-ciones que de ejecuciones, aunque en terminos tecnicos no es mas que ejecutar un programa. El terminosimulacion se suele usar en el contexto de modelos (e.g. modelado y simulacion, o modeling and simula-tion). Como nuestros programas {log} son traducciones casi mecanicas de especificaciones Z entoncespodemos decir que son modelos de los requerimientos del usuario. Por otro lado, el termino animacionse suele usar en el contexto de especificaciones formales. En ese sentido, un programa {log} puede versecomo una especificacion ejecutable. De hecho, como veremos un poco mas adelante, un programa {log}tiene propiedades que los acercan a las especificaciones y a los modelos y que en general no las tienenlos programas escritos en lenguajes de programacion imperativos (y hasta funcionales).

Sea ejecucion, simulacion o animacion, la idea basica es dar entradas al programa, modelo o espe-cificacion y observar las salidas o efectos producidos. De todas formas mostraremos que {log} ofrececiertas posibilidades mas alla de esta idea basica.

3.1. Simulaciones simples

Veamos un ejemplo de simulacion de un prototipo {log}. Consideremos el prototipo de la agenda decumpleanos asumiendo que esta almacenado en el archivo bb.pl. Empezamos ejecutando el interpreteProlog desde una terminal de comandos y desde el directorio donde instalamos {log}4.

~/setlog$ prolog

?- consult(’setlog.pl’).

?- setlog.

{log}=> consult(’bb.pl’).

{log}=> birthdayBookInit(K,B) & addBirthday(K,B,maxi,160367,K_,B_).

K = {},

B = {},

3De hecho la traduccion podrıa automatizarse, aunque probablemente no de forma completa y seguramente una traduccionmanual producira un prototipo algo mas eficiente.

4El nombre del ejecutable del interprete Prolog puede variar dependiendo del interprete que hayan instalado y del sistemaoperativo.

Page 19: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

19

K_ = {maxi},

B_ = {[maxi,160367]}

Another solution? (y/n) y

no

{log}=>

donde en cada lınea hacemos lo siguiente:

1. Ejecutamos el interprete de Prolog.

2. Cargamos el interprete {log}.

3. Entramos en el interprete {log}.

4. Cargamos el prototipo de la agenda de cumpleanos.

5. Efectuamos la simulacion:

birthdayBookInit(K,B) & addBirthday(K,B,maxi,160367,K_,B_).

la cual consiste en:

Invocar la clausula birthdayBookInit pasandole como parametros cualesquiera variables;Invocar la clausula addBirthday pasandole en los dos primeros parametros las mismas va-riables que usamos en la invocacion a birthdayBookInit; como tercer y cuarto parametrodos constantes y en los dos ultimos parametros dos variable nuevas.

Notar que la simulacion termina con un punto.

6. {log} muestra el resultado de la simulacion

7. {log} pregunta si queremos ver otras posibles soluciones a lo que respondemos que sı.

8. {log} informa que no hay mas soluciones.

Veamos con mas detalle la simulacion:

birthdayBookInit(K,B) & addBirthday(K,B,maxi,160367,K_,B_).

Cuando invocamos birthdayBookInit(K,B) se produce la unificacion de K y B con Known y Birthdayque son los parametros formales usados en la definicion de birthdayBookInit (ver el codigo completoen el Apendice A). Esto implica que K es igual a Known y B lo es a Birthday lo que a su vez implica queK y B son iguales a {}, que es lo que indica la primera lınea de la respuesta de {log}. Entonces, cuandoinvocamos addBirthday(K,B,maxi,160367,K_,B_) es como si invocaramos:

addBirthday({},{},maxi,160367,K_,B_)

La invocacion a addBirthday implica la invocacion no determinista de addBirthdayOk y nameAlreadyExists. Es decir que ambas clausulas se invocan en un orden indeterminado. Supongamos que se invocaprimero a addBirthdayOk. En este caso, se producen las siguientes unificaciones:

Known = {}

Birthday = {}

Name_i = maxi

Date_i = 160367

K_ = Known_

B_ = Birthday_

Page 20: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

20

Por lo tanto el predicado {log} de addBirthdayOk queda de la siguiente forma:

maxi nin {} &

un({},{maxi},K_) &

un({},{[maxi,160367]},B_)

lo cual reduce a lo siguiente:

K_ = {maxi} &

B_ = {[maxi,160367]}

que corresponde a la segunda lınea de la respuesta de {log}.Al pulsar ’y’ cuando {log} pregunta si queremos otra solucion se invoca la clausula nameAlready

Exists porque es la clausula que estaba pendiente de invocacion. Nuevamente se produce una serie deunificaciones:

Known = {}

Birthday = {}

Name_i = maxi

K_ = Known

B_ = Birthday

Entonces el predicado {log} de nameAlreadyExists queda de la siguiente forma:

maxi in {}

Como este predicado es evidentemente falso, significa que la invocacion de nameAlreadyExists fallay por lo tanto no produce ningun resultado. De aquı que {log} responda no cuando le pedimos otrasolucion.

La siguiente es una simulacion mas larga que incluye las dos invocaciones de la simulacion queacabamos de analizar en detalle.

birthdayBookInit(K,B) & addBirthday(K,B,maxi,160367,K1,B1) &

addBirthday(K1,B1,’Yo’,201166,K2,B2) & findBirthday(K2,B2,’Yo’,C,K3,B3) &

addBirthday(K3,B3,’Otro’,201166,K4,B4) & remind(K4,B4,160367,Card,K5,B5) &

remind(K5,B5,201166,Card1,K_,B_).

donde podemos observar que invocamos todas las operaciones definidas; que usamos diferentes variablespara encadenar los estados y capturar las salidas como Card y Card1; y que es posible ingresar constantesque empiezan con mayuscula siempre y cuando las encerremos entre comillas simples.

La solucion que retorna la simulacion anterior es:

K = {},

B = {},

K1 = {maxi},

B1 = {[maxi,160367]},

K2 = {maxi,Yo},

B2 = {[maxi,160367],[Yo,201166]},

C = 201166,

K3 = {maxi,Yo},

B3 = {[maxi,160367],[Yo,201166]},

K4 = {maxi,Yo,Otro},

B4 = {[maxi,160367],[Yo,201166],[Otro,201166]},

Page 21: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

21

Card = {maxi},

K5 = {maxi,Yo,Otro},

B5 = {[maxi,160367],[Yo,201166],[Otro,201166]},

Card1 = {Yo,Otro},

K_ = {maxi,Yo,Otro},

B_ = {[maxi,160367],[Yo,201166],[Otro,201166]}

donde podemos notar que {log} nos brinda la posibilidad de contar con una traza completa de la ejecu-cion del prototipo. Observar tambien que {log} internamente elimina las comillas simples que usamospara algunas constantes.

Una simulacion donde siempre se usara las mismas variables de estado, por ejemplo:birthdayBookInit(K,B) & addBirthday(K,B,N,C,K,B).

en general fallarıa porque serıa imposible que los valores de K y B antes de invocar a addBirthday

unificaran con los que se obtienen cuando esa clausula termina. Podrıamos usar la misma variable para elestado anterior y posterior cuando la clausula corresponde a una operacion Z que no modifica el estado(por ejemplo cuando invocamos findBirthday y remid).

Hasta el momento las dos simulaciones que realizamos las hicimos desde el estado inicial. Es muysimple iniciar una simulacion desde un estado cualquiera:K = {maxi,caro,cami,alvaro} &

B = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]} &

addBirthday(K,B,’Yo’,160367,K1,B1) & remind(K1,B1,160367,Card,K1,B1).

donde podemos ver que usamos la misma variable para indicar el estado anterior y final de remid (porquesabemos que no produce un cambio de estado). En este caso la salida es:K = {maxi,caro,cami,alvaro},

B = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]},

K1 = {maxi,caro,cami,alvaro,Yo},

B1 = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400],[Yo,160367]},

Card = {maxi,Yo}

Un problema que puede presentarse cuando se define manualmente el estado inicial para una simu-lacion es que este, por error humano, no sea consistente con, por ejemplo, el invariante de estado. Noobstante es muy simple evitar este problema como veremos en la seccion 3.4.

3.2. Simulaciones simbolicas

Ejecutar simbolicamente un programa significa ejecutarlo proveyendole variables como entradas enlugar de constantes. Esto implica que el motor de ejecucion debe ser capaz de operar simbolicamente conlas variables para ir determinando sus valores a medida que el programa avanza. Al operar con variables,una ejecucion simbolica puede mostrar propiedades mas generales de un programa que cuando se loejecuta partiendo de constantes.{log} es capaz de simular simbolicamente los prototipos, dentro de ciertos lımites. Los lımites estan

dados por la teorıa de conjuntos y las clausulas no recursivas. Las condiciones para que {log} puedarealizar simulaciones simbolicas son las siguientes5:

5Esta es una descripcion informal y no del todo precisa de las condiciones para realizar simulaciones simbolicas. Lascondiciones precisas son mas complejas y muy tecnicas. Los programas {log} con los que no se pueden hacer simulacionessimbolicas y que no cumplen las condiciones indicadas son infrecuentes en la clase de problemas con los que nos enfrentamosen este curso.

Page 22: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

22

1. No debe haber definiciones recursivas (por ejemplo la definicion de sum_da vista en la Seccion2.10).

2. Solo se usan los operadores de las Tablas 1 y 2. Si el programa {log} usa cardinalidad (size) nodebe usar los operadores de la Tabla 2. El operador de cardinalidad es completo solo en combina-cion con los operadores de la Tabla 1.

3. Todas las formulas aritmeticas son lineales6.

Es decir que el codigo {log} del prototipo no puede incluir operadores de la Tabla 3 si se quiere reali-zar simulaciones simbolicas7. En realidad, muchas simulaciones simbolicas son aun posible aunque lascondiciones de arriba no se verifique.

El codigo de la agenda de cumpleanos esta dentro de los lımites para que {log} pueda operar simboli-camente. Por ejemplo, empezando desde el estado inicial podemos invocar a addBirthday usando uni-camente variables:

birthdayBookInit(K,B) & addBirthday(K,B,N,C,K_,B_).

ante lo cual {log} responde con:

K = {},

B = {},

K_ = {N},

B_ = {[N,C]}

que es una representacion del resultado esperado. Ahora encadenamos otra invocacion mas a addBirthdayusando otro juego de variables para las entradas:

birthdayBookInit(K,B) & addBirthday(K,B,N,C,K1,B1) & addBirthday(K1,B1,M,D,K_,B_).

en cuyo caso la primera solucion de {log} es:

K = {},

B = {},

K1 = {N},

B1 = {[N,C]},

K_ = {N,M},

B_ = {[N,C],[M,D]}

Constraint: N neq M

donde podemos ver una parte de la respuesta de {log} que no habıamos visto en las simulaciones an-teriores. En efecto, la solucion mas general que puede retornar {log} consta de dos partes: una lista(posiblemente vacıa) de igualdades entre variables y terminos (o expresiones); y una lista (posiblementevacıa) de restricciones (los predicados luego de la palabra Constraint). Cada restriccion es un predi-cado {log}. La conjuncion de todas las restricciones es siempre satisfacible (en general la solucion seobtiene sustituyendo las variables de tipo conjunto por el conjunto vacıo). En este ejemplo, claramente,la segunda invocacion a addBirthday puede anadir la entrada [M,D] a la agenda si y solo si M nin {N}

(i.e. M /∈ {N}), lo cual vale si y solo si M es distinto de N.{log} retorna una segunda solucion de esta simulacion simbolica:

6Mas precisamente, las expresiones enteras son sumas o restas de terminos de la forma x*y con x o y constante. Todos losoperadores de orden estan permitidos, incluso neq.

7El problema con los operadores de la Tabla 3 es que dependen de ciertos aspectos de la teorıa de conjuntos que aun no hansido incorporados a {log}.

Page 23: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

23

K = {},

B = {},

K1 = {N},

B1 = {[N,C]},

M = N,

K_ = {N},

B_ = {[N,C]}

producto de considerar que N y M son iguales en cuyo caso la segunda invocacion a addBirthday va porla rama de nameAlreadyExists por lo que K_ y B_ resultan iguales a K1 y B1, lo cual tambien es elresultado esperado.

Claramente las simulaciones simbolicas nos permiten sacar conclusiones mas generales sobre el com-portamiento del prototipo. El siguiente ejemplo nos permite ver en forma mas amplia lo que acabamosde mencionar:

birthdayBookInit(K,B) & addBirthday(K,B,N,C,K1,B1) &

addBirthday(K1,B1,M,D,K2,B2) & findBirthday(K2,B2,W,X,K2,B2).

puesto que {log} considerara varios casos posibles en relacion a si M, N y W son iguales o no. Por ejemplo,las siguientes son las tres primeras soluciones:

K = {},

B = {},

K1 = {N},

B1 = {[N,C]},

K2 = {N,M},

B2 = {[N,C],[M,D]},

W = N,

X = C

Constraint: N neq M

Another solution? (y/n)

K = {},

B = {},

K1 = {N},

B1 = {[N,C]},

K2 = {N,M},

B2 = {[N,C],[M,D]},

W = M,

X = D

Constraint: N neq M

Another solution? (y/n)

K = {},

B = {},

K1 = {N},

B1 = {[N,C]},

K2 = {N,M},

Page 24: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

24

B2 = {[N,C],[M,D]}

Constraint: N neq M, N neq W, M neq W

En el primer caso considera W = N y por lo tanto X debe ser igual a C; el segundo es similar al primero; yen el tercero W no es ni M ni N y por lo tanto el valor de X puede ser cualquiera (¿es esto un error?). {log}retorna mas soluciones, pero algunas de ellas se repiten8.

Obviamente en las simulaciones simbolicas se pueden combinar variables con constantes. En generalcuantas menos variables se usen menos soluciones habra.

3.3. Simulaciones inversas

Normalmente en una simulacion el usuario provee las entradas y el modelo devuelve las salidas. Enocasiones resulta interesante tener la posibilidad de obtener las entradas partiendo de las salidas. Estoimplica una suerte de simulacion inversa.{log} es capaz de realizar simulaciones inversas dentro de los mismos lımites en los que es capaz de

realizar simulaciones simbolicas. En realidad, mirando con atencion el contenido de la seccion anterior,resulta bastante claro que {log} no distingue entre variables de entrada y de salida ni entre estado anteriory siguiente. Por lo tanto, para {log} simular un prototipo dando valores a las variables de entrada odandolos a las variables de salida no es muy distinto; de hecho {log} es capaz de computar solo convariables.

Veamos una simulacion inversa muy simple, donde solo damos el valor para el estado siguiente:K_ = {maxi,caro,cami,alvaro} &

B_ = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]} &

addBirthday(K,B,N,C,K_,B_).

donde la primera solucion que retorna {log} es la siguiente:K_ = {maxi,caro,cami,alvaro},

B_ = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]},

K = {maxi,caro,cami},

B = {[maxi,160367],[caro,201166],[cami,290697]},

N = alvaro,

C = 110400

Cuando la especificacion Z es determinista, el prototipo {log} tambien lo sera y por lo tanto parauna entrada determinada habra solo una solucion. Sin embargo, aun con prototipos deterministas, unasimulacion inversa puede generar un gran numero de soluciones. Este es el caso de la simulacion anterior.En efecto, en la primera solucion {log} considero el caso donde N = alvaro y C = 110400, peroesta no es la unica posibilidad. Entonces, cuando le solicitamos a {log} mas soluciones obtenemos, porejemplo:K_ = {maxi,caro,cami,alvaro},

B_ = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]},

K = {maxi,caro,alvaro},

B = {[maxi,160367],[caro,201166],[alvaro,110400]},

N = cami,

C = 290697

lo que significa que para obtener K_ y B_ podemos partir de K y B donde no esta el cumpleanos de camiy agregarlo.

8La repeticion de soluciones es un efecto secundario de {log} que por cuestiones propias de la teorıa de conjuntos sonimposibles de evitar en todos los casos.

Page 25: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

25

3.4. Evaluacion de propiedades

Al final de la seccion 3.1 mostramos como iniciar una simulacion desde un estado distinto del ini-cial. Tambien dijimos que esto tiene cierto riesgo porque al escribir manualmente el estado inicial elusuario puede cometer errores creando un estado inconsistente. En esta seccion veremos como evitar eseproblema usando una caracterıstica de {log} que es util para otras actividades de verificacion.

Consideremos el siguiente estado de la agenda de cumpleanos:

Known = {maxi,caro,cami,alvaro}

Birthday = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]}

Iniciar una simulacion desde este estado puede dar resultados incorrectos si no verifica el invariante deestado definido para la especificacion. Recordemos que el invariante es:

BirthdayBookInvBirthdayBook

known = dombirthday

Con {log} es muy simple comprobar que el estado definido arriba verifica el invariante. Primerotraducimos el invariante:

birthdayBookInv(Known,Birthday) :-

dom(Birthday,Known).

Luego invocamos birthdayBookInv pasandole el estado de mas arriba como parametro:

Known = {maxi,caro,cami,alvaro} &

Birthday = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]} &

birthdayBookInv(Known,Birthday).

ante lo cual {log} responde con los valores de Known y Birthday, lo que significa que la propiedad secumple porque de lo contrario la respuesta hubiese sido no. Si invocamos birthdayBookInv pasandoledirectamente los valores de las variables:

birthdayBookInv({maxi,caro,cami,alvaro},

{[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]}).

la respuesta es yes. Si por error hubiesemos escrito un estado que no verifica el invariante, por ejemplo(donde falta maxi en known):

Known = {caro,cami,alvaro} &

Birthday = {[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]} &

birthdayBookInv(Known,Birthday).

la respuesta de {log} serıa no.En general podemos tomar cualquier propiedad que se nos ocurra y evaluarla para ciertos valores de

sus variables. Por ejemplo, la componente Birthday, en cualquier estado, debe ser una funcion parcial.Entonces, por ejemplo, ante:

pfun({[maxi,160367],[caro,201166],[cami,290697],[alvaro,110400]}).

{log} responde yes y ante:

pfun({[maxi,160367],[maxi,201166],[cami,290697],[alvaro,110400]}).

responde no.

Page 26: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

26

4. Pruebas con {log}

Evaluar propiedades con {log} ayuda a realizar simulaciones correctas y a comprobar que la espe-cificacion misma verifica esas propiedades. Sin embargo, serıa mejor si pudieramos demostrar que laespecificacion verifica esas propiedades (en el sentido logico o matematico). A continuacion veremoscomo {log} nos permite demostrar que las operaciones de un sistema preservan un invariante de estado.

Hasta el momento hemos usado a {log} como un lenguaje de programacion (de prototipos). Sinembargo, {log} tambien es un satisfiability solver, es decir es un programa que determina si las formulasde una cierta teorıa son satisfacibles o no. En este caso la teorıa es la de conjuntos y relaciones donde seusan los operadores de las Tablas 1 y 2 combinada con el algebra lineal entera9.

Recordemos que la formula F que depende de la variable x es satisfacible si y solo si:

∃y : F(y)

En el caso de {log} la variable y se cuantifica sobre todos los conjuntos finitos. Por lo tanto, si {log}responde que F es satisfacible significa que existe (al menos) un conjunto finito que la satisface. Simetri-camente, si {log} responde que F no es satisfacible significa que no hay ningun conjunto finito que lasatisface, es decir:

∀y : ¬ F(y)

Ahora, si llamamos G(x) = ¬ F(x) y F no es satisfacible tenemos:

∀y : G(y)

lo que significa que G es verdadera para todo conjunto finito. Dicho de otro modo, G es valida respectode la teorıa de conjuntos finitos; o, equivalentemente, G es un teorema de la teorıa de conjuntos finitos.

En resumen, si {log} responde que F es insatisfacible, entonces sabemos que ¬ F es un teorema.

Para demostrar que la operacion T de una especificacion Z preserva el invariante de estado I tenemosque demostrar lo siguiente:

I ∧ T⇒ I′ (1)

Supongamos que T efectivamente preserva I. Si ejecutamos (1) en {log} obtendremos una serie de so-luciones porque (1) es un teorema y por lo tanto es satisfacible. Entonces, si queremos usar {log} parademostrar que (1) es un teorema tenemos que pedirle a {log} que vea si la negacion de (1) es insatisfa-cible. O sea tenemos que ejecutar:

I ∧ T ∧ ¬ I′ (2)

porque ¬ (I ∧ T⇒ I′)≡ ¬ (¬ (I ∧ T) ∨ I′)≡ I ∧ T ∧ ¬ I′.El unico inconveniente en usar {log} para ver si formulas como (2) son insatisfacibles, es el predicado

¬ I′. Mas precisamente el problema yace en que si usamos la negacion logica, en general, {log} no podrademostrar que la formula es insatisfacible. De todas formas la negacion logica no es necesaria en {log},

9En lo que sigue hablaremos de la teorıa de conjuntos finitos pero lo mismo vale para esta combinada con el algebra linealentera.

Page 27: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

27

mientras trabajemos con los operadores de las Tablas 1 y 2 y el algebra lineal entera. En efecto, para cadaoperador de las Tablas 1 y 2 {log} implementa su negacion (lo mismo para los operadores aritmeticos).Por ejemplo, en lugar de escribir ¬ x ∈ A, escribimos x /∈ A; en lugar de ¬ A = B, escribimos A 6= B; enlugar de ¬ pfun(f ) escribimos npfun(f ); en lugar de ¬ X > Y escribimos X ≤ Y; y ası sucesivamente. SiI′ es un predicado compuesto (por conjunciones, disyunciones, implicaciones, negaciones, etc.) entoncesdistribuimos la negacion todo lo posible y luego usamos las negaciones de los predicados atomicos.

En la especificacion Z de la agenda de cumpleanos propusimos como invariante:

dombirthday = known

Entonces para demostrar con {log} que AddBirthday preserva ese invariante, tenemos que demostrar latraduccion de:

dombirthday = known ∧ AddBirthday ∧ dombirthday′ 6= known′

es insatisfacible. O sea que si invocamos a {log} con el siguiente codigo:dom(B,K) &

addBirthday(K,B,N,C,K_,B_) &

ndom(B_,K_).

la respuesta deberıa ser no. Esto significa que la formula es insatisfacible y por lo tanto la negacion de esaformula es un teorema. Y la negacion de esa formula es, escrita en lenguaje Z, dombirthday = known ∧AddBirthday⇒ dombirthday′ = known′.

En definitiva hemos demostrado que Addbirthday preserva dombirthday = known para todo conjun-to finito. Esto no es exactamente lo mismo que hubieramos demostrado usando, por ejemplo, Z/EVESpues en ese caso lo hubieramos demostrado para todo conjunto (y no solo para los finitos). La ventajade hacerlo con {log} es que las demostraciones son automaticas. Por otro lado, el programa que imple-mente la agenda de cumpleanos jamas operara con un conjunto infinito de gente conocida por lo que lademostracion hecha con {log} resulta apropiada.

Cuando tradujimos a {log} la especificacion Z de la agenda de cumpleanos, no tradujimos la decla-racion de tipo de birthday (o sea birthday : NAME 7→ DATE). No lo hicimos porque, en un sentido, elhecho de que birthday sea una funcion parcial es mas un invariante que una declaracion de tipo (de hecholas funciones parciales no son un tipo en Z). Claramente, si normalizaramos el esquema BirthdayBookla pertenencia de birthday al conjunto NAME 7→ DATE se convertirıa en un invariante por definicion(ver Seccion 2.1.2). Entonces vamos a usar {log} para demostrar que birthday ∈ NAME 7→ DATE es uninvariante de la especificacion. Es decir vamos a suponer una declaracion normalizada y la inclusion delpredicado correspondiente en el esquema BirthdayBookInv.

En realidad, por como tradujimos la especificacion, el invariante que podemos demostrar es quebirthday es una funcion parcial. Es decir no podemos demostrar que el dominio es un subconjunto deNAME ni que el rango lo es de DATE, aunque volveremos sobre este punto un poco mas adelante.Entonces, en lugar de demostrar:

birthday ∈ NAME 7→ DATE ∧ AddBirthday⇒ birthday′ ∈ NAME 7→ DATE

vamos a demostrar

birthday ∈ 7→ ∧ AddBirthday⇒ birthday′ ∈ 7→

En ese caso la formula {log} es

Page 28: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

28

pfun(B) &

addBirthday(K,B,N,C,K_,B_) &

npfun(B_).

a lo cual {log} responde, tal vez inesperadamente, con una solucion (en lugar de responder no). Es decir,{log} nos esta diciendo que la formula que le dimos es satisfacible, o sea que no es insatisfacible, o seaque la negacion de esa formula no es un teorema. ¿Por que no es un teorema cuando nosotros estamosbastante seguros de que deberıa serlo? La respuesta que nos da {log} nos ayuda a entender el problema:

B = {[N,_N2]/_N1},

K_ = {N/K},

B_ = {[N,_N2],[N,C]/_N1}

Constraint: pfun(_N1), comppf({[N,N]},_N1,{}), N nin K, set(_N1), [N,C] nin _N1,

C neq _N2, [N,_N2]nin _N1, set(K)

Observen que B = {[N,_N2]/_N1} pero no dice que N tenga que estar en K cuando, como demostramosmas arriba, K es igual al dominio de B (y N claramente pertenece al dominio de B). Es decir que, de algunaforma, {log} encuentra un estado que viola una propiedad de la especificacion. El problema es que laespecificacion de AddBirthday establece que n? /∈ known en lugar de n? /∈ dombirthday. Entonces, altraducir la especificacion tal cual esta, se pierde el vınculo entre known y el dominio de birthday. Porotro lado, nosotros ya demostramos que known= dombirthday es un invariante; es decir, ya demostramosque eso vale siempre. Entonces lo que hacemos es agregar ese predicado como hipotesis:

dom(B,K) & %%% hipotesis

pfun(B) &

addBirthday(K,B,N,C,K_,B_) &

npfun(B_).

y ahora {log} responde no.Ahora volvemos sobre la cuestion de demostrar que el dominio de birthday es un subconjunto de

NAME y que el rango lo es de DATE, son invariantes. Como en general no tradujimos las declaraciones detipos, tenemos que asumir que los parametros que le pasamos a addBirthday, es decir N y C, pertenecena los conjuntos {log} correspondientes a NAME y DATE. Lo podemos hacer de esta forma:

N in NAME & C in DATE & %%% "tipamos" los parametros

dom(B,DB) & subset(DB,NAME) &

ran(B,RB) & subset(RB,DATE) &

addBirthday(K,B,N,C,K_,B_) &

dom(B_,DB_) & ran(B_,RB_) &

(nsubset(DB_,NAME) or nsubset(RB_,DATE)).

Ademas de demostrar que cada operacion del sistema preserva el invariante es necesario demostrarque el estado inicial lo verifica (porque de lo contrario el sistema comenzarıa a ejecutar en un estadoque viola el invariante y en consecuencia las operaciones no tendrıan nada que preservar). En generalesta demostracion es mucho mas simple. Comenzamos demostrando que el estado inicial verifica quedombirthday = known:

birthdayBookInit(K,B) &

ndom(B,K).

Continuamos demostrando que en el estado inicial birthday es una funcion parcial:

Page 29: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

29

birthdayBookInit(K,B) &

npfun(B).

y terminamos demostrando que en el estado inicial el dominio y el rango de birthday son subconjuntosde NAME y DATE, respectivamente:

birthdayBookInit(K,B) &

dom(B,DB) & ran(B,RB) &

(nsubset(DB,NAME) or nsubset(RB,DATE)).

Referencias[1] Maximiliano Cristia (2017): Introduccion a la notacion Z. http://www.fceia.unr.edu.ar/asist/a-z.

pdf. Apunte de clase - Ingenierıa de Software 1.[2] J. M. Spivey (1992): The Z notation: a reference manual. Prentice Hall International (UK) Ltd., Hertfordshire,

UK, UK.

A. Codigo {log} de la agenda de cumpleanos

birthdayBookInit(Known,Birthday) :-

Known = {} &

Birthday = {}.

birthdayBookInv(Known,Birthday) :-

dom(Birthday,Known).

addBirthday(Known,Birthday,Name_i,Date_i,Known_,Birthday_) :-

addBirthdayOk(Known,Birthday,Name_i,Date_i,Known_,Birthday_)

or

nameAlreadyExists(Known,Birthday,Name_i,Known_,Birthday_).

addBirthdayOk(Known,Birthday,Name_i,Date_i,Known_,Birthday_) :-

Name_i nin Known &

un(Known,{Name_i},Known_) &

un(Birthday,{[Name_i,Date_i]},Birthday_).

nameAlreadyExists(Known,Birthday,Name_i,Known_,Birthday_) :-

Name_i in Known &

Known_ = Known &

Birthday_ = Birthday.

findBirthday(Known,Birthday,Name_i,Date_o,Known_,Birthday_) :-

findBirthdayOk(Known,Birthday,Name_i,Date_o,Known_,Birthday_)

or

notAFriend(Known,Birthday,Name_i,Known_,Birthday_).

findBirthdayOk(Known,Birthday,Name_i,Date_o,Known_,Birthday_) :-

Page 30: floggpara Ingenier´ıa de Software - Facultad - FCEIA · 2019. 10. 1. · Apunte de clase floggpara Ingenier´ıa de Software Maximiliano Cristia´ Licenciatura en Ciencias de la

30

Name_i in Known &

apply(Birthday,Name_i,Date_o) &

Known_ = Known &

Birthday_ = Birthday.

notAFriend(Known,Birthday,Name_i,Known_,Birthday_) :-

Name_i nin Known &

Known_ = Known &

Birthday_ = Birthday.

remind(Known,Birthday,Today_i,Cards_o,Known_,Birthday_) :-

rres(Birthday,{Today_i},M) &

dom(M,Cards_o) &

Known_ = Known &

Birthday_ = Birthday.