Programaión Orientada a la Inteligenia Artiial Curso: 5 Tiempo: NO se permite NINGÚN material auxiliar NI aluladora Advertenias: Deben responderse en hojas Poner el nombre en todas separadas o 2h. las uestiones de LISP y PROLOG. las hojas. Se valorará espeialmente el estilo, la adeuada dou- mentaión del ódigo, que el examen esté ompensado y que no inluya errores oneptuales importantes. 2 a Semana. Febrero 2006 PROBLEMA 1 (lisp). VALORACIÓN 2.75 El estado atual en ierto problema de búsqueda se representa mediante una lista de eros y unos. a) Crear una funión Lisp, deimal, que devuelva el valor deimal del número binario representado por un estado ualquiera. Para ello utilie una funión, elevar, que aepte un número variable de enteros no negativos y devuelva el resultado de elevar el primer número al segundo, el resultado al terero, et. Por ejemplo, (elevar 2 2 2) > 16 o (elevar 2 3 2 1) > 64. En el diseño de esta funión no se permite utilizar ningún omando Lisp que eleve un número a otro. b) Crear una funión Lisp, ambiar-valores, que dado un estado y una másara on la misma estrutura que un estado, ambie ada valor del estado sólo si en el orrespondiente valor de la másara hay un 1. Si el valor orrespondiente de la misma es un 0, no se ambiaría el valor del estado. Por ejemplo, (ambiar-valores '(0 1 1 0 1) '(1 0 0 1 1)) > (1 1 1 1 0), donde la primera lista es un estado y la segunda una másara. SOLUCIÓN, por Severino Fernández Galán (defun deimal (estado) ;; Devuelve el valor deimal del numero ;; binario representado por el estado (let ((resultado 0)) (dotimes (i (length estado) resultado) (setf resultado (+ resultado (* (first (nthdr i (reverse estado))) (elevar 2 i))))))) (defun elevar (&rest numeros) ;; Aepta un numero variable de enteros no negativos y ;; devuelve el resultado de elevar el primero al segundo, ;; el resultado al terero, et. (let ((resultado (first numeros)) resultado-aux) ; aumulador de resultado al ambiar exponente (ase resultado (0 0) (1 1) (t (dolist (exponente (rest numeros) resultado) (when (= 0 exponente) 1 (return 1)) (setf resultado-aux 1) (dotimes (i exponente) (setf resultado-aux (* resultado-aux resultado))) (setf resultado resultado-aux)))))) (defun ambiar-valores (estado masara) ;; Cambia el valor de un estado segun una masara (if (null estado) nil (if (= 1 (first masara)) (if (= 0 (first estado)) (ons 1 (ambiar-valores (rest estado) (rest masara))) (ons 0 (ambiar-valores (rest estado) (rest masara)))) (ons (first estado) (ambiar-valores (rest estado) (rest masara)))))) PROBLEMA 2 (lisp). VALORACIÓN 2.75 Considere un grafo formado por una lista de nodos. Cada nodo lo representamos omo una lista propiedad on las siguientes propiedades: hijos (que es una lista de símbolos, por ejemplo, '(A C D)) y padres (que también es otra lista de símbolos). a) Construya una funión Lisp que devuelva en una lista los nodos sin padres o sin hijos del grafo. b) Construya una funión Lisp que devuelva en una lista los anteesores de ierto nodo. ) Construya una funión que invierta el sentido de los aros que entran y salen de un nodo dado. SOLUCIÓN, por Severino Fernández Galán (defun sin-padres-o-hijos (grafo) (let (resultado) (dolist (nodo grafo resultado) (if (or (es-nodo-sin 'padres nodo grafo) (es-nodo-sin 'hijos nodo grafo)) (setf resultado (ons nodo resultado)))))) (defun es-nodo-sin (riterio nodo grafo) (let ((resultado t) (riterio-aux)) (if (eq riterio 'padres) (setf riterio-aux 'hijos) (setf riterio-aux 'padres)) (dolist (nodo-i grafo resultado) (if (member nodo (get nodo-i riterio-aux)) 2 (return nil))))) (defun anteesores (nodo) (let ((resultado) (padres (get nodo 'padres))) (when padres (setf resultado (introduir-sin-repetiion padres resultado)) (dolist (padre padres resultado) (setf resultado (introduir-sin-repetiion (anteesores padre) resultado)))))) (defun introduir-sin-repetiion (lista1 lista2) ;; Hae la union de los elementos de lista1 y lista2 ;; No debe haber repetiion de elementos ;; Se supone que lista1 y lista2 no tiene elemento repetidos por separado (let ((resultado lista1)) (dolist (elemento lista2 resultado) (if (not (member elemento resultado)) (setf resultado (ons elemento resultado)))))) (defun invertir-aros (nodo) (let ((padres (get nodo 'padres)) (hijos (get nodo 'hijos))) (dolist (padre padres) (invertir-aro padre nodo)) (dolist (hijo hijos) (invertir-aro nodo hijo)))) (defun invertir-aro (nodo1 nodo2) ;; Invierte el aro que va de nodo1 a nodo2 (setf (get nodo1 'hijos) (remove nodo2 (get nodo1 'hijos))) (setf (get nodo1 'padres) (ons nodo2 (get nodo1 'padres))) (setf (get nodo2 'hijos) (ons nodo1 (get nodo2 'hijos))) (setf (get nodo2 'padres) (remove nodo1 (get nodo2 'padres)))) PROBLEMA 3 (prolog). VALORACIÓN 3.00 La empresa aguas-potables.om posee una base de datos PROLOG de artíulos de ingeniería. Se muestra una parte de dihos datos: %Revistas revista('TECNOLOGIA DEL AGUA',001). revista('MEDIO AMBIENTE',002). %Artíulos 3 artiulo(1,001, 'La osmosis inversa y su apliaion en la desalaion de aguas'). artiulo(2,002, 'Eliminaion de nutrientes'). artiulo(3,001, 'Determinaion y difereniaion de esherihia oli y oliformes totales'). artiulo(4,001, 'Tratamientos eletroquimios de desinfeion'). %Palabras lave palabra_lave('agua residual',1). palabra_lave('osmosis',1). palabra_lave('desalaion',1). palabra_lave('agua salobre',1). palabra_lave('agua residual',2). palabra_lave('nitrifiaion',2). palabra_lave('desnitrifiaion',2). palabra_lave('agua potable',3). palabra_lave('esherihia',3). palabra_lave('agua residual',4). palabra_lave('desinfeion',4). palabra_lave('eletroquimia',4). La meta-desripión de los datos es la siguiente: revista(<título>, <n o referenia revista>). o o artiulo(<n referenia artíulo>, <n referenia revista a la que pertenee el artíulo>, <título del artíulo>). palabra_lave(<palabra lave>, <n o referenia del artíulo al que se le asigna esta palabra lave>). La empresa nos enarga realizar el prediado palabras_lave/1, uyo objetivo se umple uando su argumento ontiene el listado de todas las palabras lave existentes en la base de datos, pero sin repetir. Así, on la base de datos anterior, obtendríamos un resultado omo el siguiente: ?- palabras_lave(L). L=['agua residual','osmosis', 'desalaion','agua salobre', 'nitrifiaion','desnitrifiaion', 'agua potable','esherihia', 'desinfeion','eletroquimia'℄ Yes. Se pide: El ódigo del prediado palabras_lave/1 onvenientemente omentado y expliado. 4 Desribir el funionamiento de diho prediado mediante la traza no exhaustiva 1 del ejemplo anterior. SOLUCIÓN, por Félix Hernández del Olmo %Revistas revista('TECNOLOGIA DEL AGUA',001). revista('MEDIO AMBIENTE',002). %Artíulos artiulo(1,001, 'La osmosis inversa y su apliaion en la desalaion de aguas'). artiulo(2,002, 'Eliminaion de nutrientes'). artiulo(3,001, 'Determinaion y difereniaion de esherihia oli y oliformes totales'). artiulo(4,001, 'Tratamientos eletroquimios de desinfeion'). %Palabras lave palabra_lave('agua residual',1). palabra_lave('osmosis',1). palabra_lave('desalaion',1). palabra_lave('agua salobre',1). palabra_lave('agua residual',2). palabra_lave('nitrifiaion',2). palabra_lave('desnitrifiaion',2). palabra_lave('agua potable',3). palabra_lave('esherihia',3). palabra_lave('agua residual',4). palabra_lave('desinfeion',4). palabra_lave('eletroquimia',4). %Mapeo del prediado de un solo argumento a % otro prediado on un segundo argumento (auxiliar). palabras_lave(L) :- palabras_lave(L,[℄). %Ahora, el primer argumento va ontieniendo las palabras lave soluión. %El segundo argumento almaena las palabras que ya han ido apareiendo. palabras_lave([P|L℄,Palabras) :- palabra_lave(P,_), not(member(P,Palabras)), palabras_lave(L,[P|Palabras℄). %Finalmente, el prediado terminaión. Para que el bule sea finito. palabras_lave([℄,_). 1 Desriba la traza del programa de una manera general, y éntrese en los detalles sólo uando sea neesario. 5 PROBLEMA 4 (prolog). VALORACIÓN 1.50 Construir el prediado de la lista L. ultimo(X,L), uyo objetivo se umple si el elemento X es el último elemento Comprobar su funionamiento mediante la traza no exhaustiva de algún ejemplo. SOLUCIÓN, por Félix Hernández del Olmo Ver página 144 del libro de texto: %O es el únio elemento de la lista. ultimo(X,[X℄). %O si no, tiene que estar en el "resto" (al final) % de la lista ultimo(X,[_|Y℄) :- ultimo(X,Y). 6