Prolog - Apunte explicativo

March 27, 2018 | Author: Aline Jannet García Ornelas | Category: First Order Logic, Logic, Programming Language, Mathematical Proof, Computer Programming


Comments



Description

Paradigmas de ProgramaciónProgramación Lógica Compendio sobre bibliografías varias Coordinadora: Profesora Mirta Pérez Alumnos: Alejandro Acquesta Florencia Bryant Diego Fernández César D’Onofrio Junio de 1997 Revisado por Fernando Dodino Febrero de 2000 Apunte de Paradigma Lógico Paradigmas de Programación Introducción El paradigma lógico, que resultó una apasionante novedad en la década del 70, tiene como característica diferenciadora el hecho de manejarse de manera declarativa y con la aplicación de las reglas de la lógica. Esto significa que en lugar de basarse, como en el caso de los paradigmas procedurales, en el planteo del algoritmo para la resolución del problema, se basa en expresar todas las condiciones del problema y luego buscar un objetivo dentro de las declaraciones realizadas. Esta forma novedosa de tratamiento de la información llevó a pensar en un determinado momento en la revolución que significaría la existencia de “programas inteligentes” que pudieran responder, no por tener en la base de datos determinados conocimientos, sino por poder inferirlos a través de la deducción. Los japoneses en particular hacia fines de la década del 70 pusieron un gran énfasis en el desarrollo de las computadoras de quinta generación, que tanto desde el punto de vista del hardware como del software serían totalmente novedosas. En las páginas siguientes trataremos de dar un breve pantallazo de las características, con el modesto objetivo de conseguir que los alumnos de la materia paradigmas de programación puedan diferenciar los casos de conveniencia de aplicación del paradigma, con un pequeño conocimiento de sus pautas generales y algún lenguaje de programación y, sobre todo incentivar la propia inquietud de investigar y conocer. 2 Apunte de Paradigma Lógico Paradigmas de Programación Paradigma lógico Enunciaremos a continuación algunos de los antecedentes históricos de la generación del paradigma que se remontan a la utilización de la lógica para la resolución del problema hasta la más reciente creación del lenguaje Turbo Prolog que utilizaremos en el presente curso. 1870 Charles S. Pierce realiza una descripción de una notación relativa a la lógica como una ampliación de los conceptos del algebra de Boole para posibles cálculos lógicos. 1889 Giuseppe Peano ublica “Principios de aritmética, nueva exposición del método”, donde se aplica por primera vez, una sistematización de las matemáticas con una notación funcional. 1896 Charles S. Pierce publica “Una teoría de inferencia problable”, donde propone una notación gráfica para las matemáticas llamada grafos existenciales, que él la llamó “la lógica del futuro”. 1951 Alfred Horn ublica “Sobre sentencias las cuales son verdaderas de la unión directa de las álgebras”, en la cual presenta un modelo lógico ara el tratamiento de oraciones del lenguaje natural”. 1972 En la Universidad de Marsella, Alain Colmerauer y un grupo de investigadores presentan el lenguaje PROLOG ( que utiliza el método de Horn) como una herramienta para resolver ciertos problemas en el área de la inteligencia artificial, originalmente vinculados al tratamiento computacional del lenguaje natural. Más tarde en la Universidad de Edinburgo se erfeccional el lenguaje y se comienza a escribir el compilador. 1974 Robert Kowalski ublica “Predicados lógicos como un lenguaje de programación”, donde crea el Paradigma Lógico como un paradigma de programación. 1979 Robert Kowalski publica “Lógica para la resolución de problemas y junto con la Universidad de Edinburgo escriben un nuevo compilador para el Prolog, adaptándolo al aradigma lógico planteando la ecuación Lógica + control + estructuras de datos = programas. 1986 Borland Internacional presenta el primer compilador comercial Prolog para PC. 3 Apunte de Paradigma Lógico Paradigmas de Programación Al plantearse el análisis de un nuevo paradigma comienza la inquietud acerca del tipo de problemas que pueden resolverse a través del mismo. Además de las características básicas enunciadas en la introducción acerca del paradigma lógico como declarativo, podemos decir que este es ampliamente utilizado en las aplicaciones que tienen que ver con la Inteligencia Artificial, particularmente en dos campos:  Sistemas Expertos y  Procesamiento de Lenguaje Natural. Un sistema experto es un programa que imita el comportamiento de un experto humano. Por lo tanto contiene información (es decir una base de conocimientos) y una herramienta para comprender las preguntas y encontrar la respuesta correcta examinando la base de datos (un motor de inferencia). E s q u e m a d e u n a a p lic a c ió n b a s a d a e n e l p a r a d ig m a ló g ic o A b s t r a c c ió n d e la R e a lid a d M o t o r d e in f e r e n c ia O b je t iv o s : c o n s u lt a s B a s e d e c o n o c im ie n t o s . H echos . R e g la s En el caso del procesamiento del lenguaje humano se trata de dividir el lenguaje en partes y relaciones y tratar de comprender su significado. Para plantear los problemas en términos del paradigma lógico, debemos poder en primer lugar plantearlos en términos de reglas lógicas. Las reglas matemáticas para poder reducir sentencias textuales a representaciones simbólicas existen desde hace años, pero en 1965 Robinson descubrió el principio de resolución el cual mostraba como estas representaciones podían ponerse de forma adecuada y dárselas a una computadora para su análisis. La resolución es una regla de inferencia que premite a la computadora decir qué proposiciones siguen lógicamente a otras proposiciones. El software que utiliza el principio de resolución trabaja con cláusulas lógicas. Utiliza la unificación para intentar identificar las partes derecha e izquierda de las cláusulas de una forma lógica, investigando los valores de la variable que permitirá una identificación correcta. 4 Apunte de Paradigma Lógico Paradigmas de Programación La aplicación de la lógica a la resolución de problemas se puede ver desde este punto de vista como la modelización a través de un conjunto de fórmulas. Si la representación es buena hay al menos una interpretación que es modelo de dichas fórmulas, es la especificación del problema. Luego se trata de sacar conclusiones: demostrar teoremas a partir de las fórmulas iniciales tomadas como axiomas. Revisar todas las interpretaciones es obviamente impracticable. La posibidad que se abre con la lógica de primer orden es operar a través de reglas de inferencia. Se llega a las mismas conclusiones siempre y cuando el conjunto de las reglas de inferencia formen un sistema consistente y completo. El problema es que esta elección se puede resolver de distintas maneras, dando lugar a diferentes estrategias. Una estrategia significa la elección de un camino que vaya desde el conjunto inicial hasta la cláusula vacía. El control del proceso deductivo es central en el paradigma lógico. Hay dos caminos fundamentales 1) A través de técnicas generales independientes del dominio. 2) Agregar conocimiento acerca del conocimiento (metaconocimiento) en general vinculado a la aplicación. Una forma de orientar la búsqueda es a partir del teorema a probar. Partiendo de este objetivo, descomponerlo en subobjetivos, hasta llegar a hechos conocidos. Este método es el conocido como encadenamiento hacia atrás (backward chaining). La intención es que la presencia del objetivo disminuya las deducciones irrelevantes. Esta estrategia es parte de la implementada en Prolog. La segunda idea la de la lectura procedural, imagina a cada cabeza de cláusula (conclusión) como el nombre de un procedimiento y a cada elemento del cuerpo (condición) como una llamada a un procedimiento que tendrá éxito si unifica (por sustitución de variables) con un nombre de procedimiento ( la cabeza de otra cláusula). Si el árbol de ejecución que se va generando mediante las sucesivas llamadas tiene todos sus nodos terminales, ( no convocan a nuevos procedimientos), la demostración tuvo éxito y en la concatenación de la sustitución de variables está la solución del objetivo. El uso de la lógica por lo tanto en la resolución de problemas, tiene que ver con pensar el problema como una teoría, expresarla en el lenguaje de la lógica e intentar alcanzar una solución como una demostración de un teorema a partir de dicha teoría. Una demostración en particular es el de resolución. Una forma en particular es manejar solo clausulas de Horn, y dentro de este marco Prolog implementa una estrategia de búsqueda en particular. 5 Una consulta consiste en hacer una pregunta acerca de si se cumple o no una cierta relación entre objetos. Un programa define un conjunto de consecuencias que constituyen su significado. Consultas La segunda forma de sentencia de un programa lógico es la consulta. Por ej.: padre (juan. La descripción de un problema mediante el lenguaje Prolog consiste en la definición de hechos y reglas que afectan a los objetos que protagonizan el problema en cuestión. maría)? Responder una consulta consiste en determinar si es una consecuencia lógica del mismo. 6 . Usa como regla de inferencia el principio de resolución de Robinson. que se obtiene de aplicar las reglas de deducción o inferencia. La primera y más simple regla de deducción es la identidad.maría) gusta(juan. El arte de la programación lógica es construir concisos y elegantes programas que tengan el significado deseado. Estructuras básicas Los elementos básicos de la programación lógica son  Sentencias  términos Las sentencias básicas son • hechos • consultas • reglas Hechos El hecho establece una relación entre objetos.: padre(juan. y el hecho se termina con un punto. Fue desarrollado como decíamos al comienzo por Alan Colmeraurer en la década del 70 en la Universidad de Marsella. Convenciones de notación: Nombres de predicados y átomos con minúsculas. La ejecución del mismo corresponde a la deducción de las consecuencias del programa. alejandra) Esta relación se llama predicado y los nombres de los individuos átomos. Si un hecho idéntico a la consulta es hallado responderá true. Esto significa encontrar este hecho como tal en la base de conocimientos.Apunte de Paradigma Lógico Paradigmas de Programación Programa lógico Un programa lógico consiste en un conjunto de axiomas y reglas que definen relaciones entre objetos. Prolog es un lenguaje de programación lógica basado en la lógica de Primer Orden. Ej. el nombre del predicado se antepone a los átomos correspondientes. padre(juan. Esto lleva a otra regla de deducción la instanciación de una sentencia universalmente cuantificada P se deduce Po para toda sustitución o. Veremos un ejemplo más adelante.Bn. sustituciones e instancias. Una variable lógica significa la especificación de un individuo indeterminado. Por ej. sino una indeterminación con respecto a la identidad. Def C es una instancia común de A y B si existen sustituciones c1 y c2 / C=Ac1=Bc2 . 7 .. Las consultas y términos que no contienen variables se llaman “ground”. Consultas existenciales Las variables de las consultas están cuantificadas existencialmente. En este caso se dice que A y B unifican o “matchean”.. como la del ejemplo. padre(juan. P o. Reglas Las reglas nos permiten definir nuevas relaciones en función de otras ya existentes. En general una consulta existencial puede tener varias soluciones. para cualquier sustitución o. Las constantes y variables son términos.B1. Las variables tienen aquí un significado distinto al del que tienen en los lenguajes del paradigma imperativo: no son una posición de memoria. Hechos universales Pueden usarse variables en hechos permitiendo generalizar una relación para todos los individuos. Estas reglas y los hechos y consultas pueden verse como cláusulas de Horn.Apunte de Paradigma Lógico Paradigmas de Programación Variables lógicas. Las reglas tienen la forma A:. Valores de una variable: en este paradigma no se produce el llamado efecto de lado. Un hecho es una regla con n = 0. Tanto A como B i son predicados. Las variables que aparecen en las reglas están cuantificadas universalmente y su alcance es toda la regla.b2. ya que una variable una vez ligada a un valor no puede cambiar de estado.X) se lee como existe un X para el que Juan sea el padre? La generalización es otra regla de deducción que puede ser utilizada: una consulta existencial P es una consecuencia lógica de una instancia de la misma. para n ≥ 0 A es la cabeza o consecuente y los B i son los antecedentes.. Convención de notación: Las variables se colocan con letras mayúsculas.X)? para obtener la respuesta X=maria Una consulta que contiene variables se debe comprender como encontrar los valores que se pueden asignar a la variable para que la consulta sea una consecuencia lógica del programa.. • Load configurationCarga antigua configuración. • Miscellaneous settings Permite cambiar el adaptador de gráficos.O.exe (ver Options). Setup: Presenta la siguiente lista de opciones: • Colors Permite cambiar los colores de las ventanas. • Module list Inicia el trabajo sobre un modulo de proyecto • Zap file in editor Limpia la ventana del Editor • Erase Borra un Archivo • Operating system Simula el entorno D. • Save configuration Graba nueva configuración. Files: Despliega el siguiente menú: • Load Carga un Archivo al Editor • Save Guarda el Archivo del Editor a la ruta especificada • Directory Cambia el Directorio de Trabajo • Print Imprime el programa • Copy Copia el programa a la ruta especificada • Rename Renombra el programa • File name Muestra (y permite cambiar) que Archivo está en el Editor. Options: Abre un menú que informa que tipo de compilación está actualmente seleccionada. en un programa objeto (OBJ File) y en un programa ejecutable (Exe File). Quit: Sale del entorno Prolog. en un programa. Edit: Activa la ventana Editor (Ver Editor).S. 8 . y permite cambiarla entre compilación en memoria (Memory).obj o en un programa.Apunte de Paradigma Lógico Paradigmas de Programación El Editor Prolog: El editor Prolog contiene siete opciones principales y cuatro ventanas de trabajo. La compilación puede ser en memoria. la autocarga de mensajes y el tamaño de la pila de trabajo. se ejecutará el programa que está en la ventana Editor. • Directories Permite cambiar las rutas de los directorios de trabajo. Las opciones son: • Run • Compile • Edit • Options • Files • Setup • Quit Run: Cuando se selecciona esta opción (usando las teclas del cursor y pulsando Enter). • Window size Permite cambiar los tamaños de las ventanas. Compile: Esta opción es usada para compilar. y el intérprete Prolog interactúa con nosotros esperando sucesivas consultas (Goal:_). cadena= string “ “ “ cadena como una cadena de caracteres.Apunte de Paradigma Lógico Paradigmas de Programación • • • • Las ventanas de trabajo son: Editor Message Trace Dialog Editor: Esta ventana nos permite escribir/ modificar programas. Message: Nos brinda información acerca del estado de ejecución/ error del programa en curso. En la sección predicates se declaran las relaciones permitidas a lo largo del programa y su/s argumento/s. numero= integer “ “ “ número como un número entero. item= symbol “ “ “ ítem como un grupo de símbolos. Dialog: Esta ventana se activa cuando ejecutamos un programa correcto que no tenga objetivos internos. coleccion= item* “ “ “ colección como una lista de átomos ítem. La Programación Prolog: Secciones de un programa Prolog. Si la relación tiene solo un argumento se las llama relación simple. precio= real “ “ “ precio como un número real. En la sección domains se establece que valores pueden tomar los distintos átomos que participan del programa.nombre) año(número) mes(número) 9 . Estos argumentos pueden ser tanto átomos como otras relaciones. predicates. Si el programa presenta errores sintácticos. Trace: Nos muestra paso a paso la línea actualmente analizada por el intérprete. predicates varon(nombre) progenitor(nombre. por el contrario si tienen más de un argumento se las denomina relaciones múltiples. Un programa Prolog cuenta con cuatro secciones: domains. goal y clauses. Por ejemplo: domains nombre= symbol define al átomo nombre como un grupo de símbolos. o sea sus dominios. la ejecución se abortará y volveremos a la ventana Editor. En este último caso se los llama Functores. La cantidad de argumentos de una relación también recibe el nombre de aridad. Por ejemplo si se le pregunta varon(Quien) buscará unificar (match) la consulta con las cláusulas. si es que el programa los tiene. Sección de declaración de Predicados. Hecho. varon(nicolas). Prolog mostrará goal:_ esperando que se le haga una consulta (goal). Hecho. clauses varon(león). Hecho. Hecho. Hecho. Un hecho es la declaración de una determinada instancia de una relación. progenitor(león.Apunte de Paradigma Lógico Paradigmas de Programación día(número) fecha(año(número). por ejemplo: domains Sección de declaración de Átomos. Tanto los hechos como las reglas deben estar seguidas de un punto. mes y día son Functores. Hecho.matilda). Pero la potencia de Prolog se manifiesta cuando usamos relaciones múltiples y reglas. la respuesta sería: True (verdadero) De esto se desprende que una consulta puede ser una búsqueda o una validación. seguida de if (o :-) y las relaciones (separadas por comas) que deben cumplir esos argumentos para que la cabeza sea un hecho. mujer(laura). Regla. mujer(matilda). Hecho. Sea el siguiente programa Prolog: domains nombre=symbol predicates varon(nombre) mujer(nombre) clauses varon(marcos). Sección de declaración de Átomos. varon(X). Relación varón. puesto que un programa con objetivos (goals) internos no activará la ventana de Dialogo. padre(X. Ejemplo. La Programación Prolog se basa en la generación de una Base de Conocimiento y la posterior consulta a la misma en busca de hechos explícitamente declarados u otros que se puedan Inferir de los antedichos (mediante el empleo de reglas).día(número)) En este caso año. Átomo nombre definido como alfanumérico.Y) if progenitor(X. Sección de declaración de Hechos y Reglas. En la sección goal se establecen los objetivos internos. Entre ellos se deben establecer los mensajes que el programa nos mostrará. En la sección clauses se declaran los hechos y las reglas de formación de hechos. Una regla está formada por una cabeza. Al ejecutar el programa anterior. Relación mujer. mujer(victoria).mes(número). 10 . que tendrá la forma de una relación de argumentos genéricos. Principio de Funcionamiento. Los objetivos a cumplir deben estar separados por comas y el último debe estar seguido de un punto.Y). su respuesta será: Quien= marcos Quien= nicolas Si la consulta fuera mujer(victoria). En el ejemplo si preguntamos padre(mirta.Y) :-progenitor(X. progenitor(mirta.paola) debe demostrar progenitor(carlos. mujer(nombre) Relación mujer. Hecho. con lo que unifica carlos con X y paola con Y. Ambas las encontrará como hechos así que devolverá Verdadero (True). ahora deja una marca para el Backtraking y aumenta un nivel de interioridad buscando solución a progenitor(mirta.Quien) con progenitor(mirta. Regla. De la regla se desprende que para demostrar padre(carlos.juan). Nótese que los átomos se inician con minúscula como juan o carlos.Y). Es aquí donde el interprete regresa al estado 11 . la respuesta se obtendrá como resultado del siguiente análisis. obteniendo así la primera respuesta.Apunte de Paradigma Lógico Paradigmas de Programación nombre=symbol Átomo nombre definido como alfanumérico. paola).Y):-progenitor(X.nombre) Relación padre.paola). Hecho. Si se le pregunta progenitor(mirta.Y). pero la segunda Falsa. progenitor(carlos. Hecho. La primera resulta Verdadera.nombre) Relación progenitor.juan) unificando Quien con juan y mostrándolo.varon(X) unificando mirta a X y juan a Y. Si le consultáramos mujer(paola). por lo que la unificación de la consulta original con esta regla resultó ser inútil. varon(X). Hasta ahora solo ha unificado sus consultas con hechos.Y):-progenitor(X. Primero lograría aparear la consulta con la cabeza de la regla padre(carlos. mujer(mirta).Y).paola) y varon(carlos). varon(carlos). Hecho.paola) con padre(X.juan). mujer(paola). Para este caso Prolog hace uso del principio llamado Backtraking (ver más abajo). A continuación comparará varon(Quien) con varon(carlos) logrando la segunda respuesta. Comparará primero varon(Quien) con varon(juan). progenitor(nombre. En pantalla mostrará todas las soluciones y dirá cuantas encontró.Quien) con progenitor(carlos. encontrándose la consulta desmenuzada en múltiples subconsultas (subgoal) distintas a la original. varon(juan). Hecho.juan) y a varon(mirta) desde el principio.varon(X). Hecho. varon(nombre) Relación varon. Si se le pregunta varon(Quien) buscará aparear la consulta con las cláusulas. predicates Sección de declaración de Predicados. padre(nombre.Quien) apareará progenitor(mirta. clauses Sección de declaración de Hechos y Reglas. y que las Variables se inician con mayúscula como Quien o X. Sin embargo es posible que no encuentre la respuesta luego de haber hecho una o más apareos con reglas. termina la búsqueda. En primer lugar se aparea la consulta padre(mirta. luego intentará unificar progenitor(mirta.juan) con la cabeza de la regla padre(X. Al no encontrar otra declaración de progenitor. luego de descender en la lista de cláusulas encontraría una unificación de nivel 0 (match ground) mujer(paola) con mujer(paola) por lo que daría como resultado Verdadero (True). que sucedería si se le preguntase padre(carlos.paola) al comparar los átomos mirta con carlos abortará el intento y continuará con la siguiente cláusula. y unificará Quien con juan. padre(X. Y). la sentencia continua (mi objetivo es probar que prueba es verdadero). Luego imprimo un <ENTER> y sigo con el siguiente hecho. y nl emite un carácter <ENTER> (o retorno de carro). nl.Resultado = 3 + 2. el programa será la definición exacta del problema. y el predicado prueba falla.varon(X). En programación lógica.juan) Verdadero Las variables en Prolog Sea el siguiente programa: varon(mirta) Falso domains predicates prueba goal prueba. Para entender el concepto de variable. Resultado ya está asignado a 5. write (Resultado). ¿qué sucede al ejecutarse? Aparece en pantalla 5 false. Como esta es la última cláusula el análisis termina y la respuesta será que la afirmación padre(mirta. Corolario La variable no se puede asignar una vez ligada a un valor. en él se expresarán los datos y todas las reglas o restricciones que se cumplen para ellos. Particularidades del lenguaje Prolog. que pide que la variable Resultado sea igual a 3 – 2. Prueba será verdadero si se logran verificar los cuatro antecedentes: Resultado debe ser igual a 3 + 2. veamos paso por paso cada hecho.juan) es Falsa. por lo tanto. antes debe procesarse la información del mismo para llevarlo a la 12 . y como ambos hechos se cumplen. y por eso el hecho X = X + 1 es siempre falso en Prolog. por lo tanto. write (Resultado). se produce una comparación 5 <> 1. se produce una asignación de Resultado a 5. El siguiente hecho imprime el valor 5 por pantalla. padre(mirta.2. Resultado = 3 .Apunte de Paradigma Lógico Paradigmas de Programación donde dejó la marca y sigue analizando la cláusula siguiente a padre(X. Donde el predicado write emite por pantalla variables o literales. clauses prueba:.Y):progenitor(X. No aparece en el programa el algoritmo de resolución.juan) Falso. Como inicialmente Resultado no está ligado a ningún valor. Sin embargo tal problema no puede expresarse sencillamente como se lo piensa. La Programación en Prolog y en forma más general en el paradigma lógico requiere de una concepción especial de lo que es un programa. progenitor(mirta. Luego de unificar X con chopper. Entonces.Apunte de Paradigma Lógico Paradigmas de Programación forma clausal. logra aparear gusta(marcos.negro). Backtracking: “volver atrás y probar de nuevo” Mediante este mecanismo. color(chopper. Supongamos el goal externo: gusta(marcos.negro) y 13 .Cual). varon(X). hermano(X. Prolog atiende la llamada de la primer subconsulta: perro(X). El apareo con la cabeza de la regla hace que Prolog trate de satisfacer la regla analizando el conjunto de subconsultas que componen el cuerpo de la misma.negro).progenitor(Z.negro). Prolog comienza desde el principio del programa buscando un apareo con algún hecho o regla.Y). En este caso.negro). se produce un nuevo llamado a color(X.Y). La variable X se unifica con el valor chopper.X). el llamado falla y se pone en funcionamiento el mecanismo de backtracking. Entonces.remo) hermano(pericles.symbol) perro(symbol) color(symbol.X) if perro(X) and color(X.Cual) con la última cláusula del programa. La unificación tiene éxito y la variable Cual se unifica con la variable X. Luego trata de responder al llamado perro(X) a partir del lugar marcado. Prolog puede encontrar todas las soluciones posibles a un problema dado. Esto le permite conocer dónde deberá comenzar a buscar el próximo apareo posible con perro(X). Prolog regresa a la última marca colocada y las variables que habían sido unificadas desde entonces se liberan.varon(X). Prolog no encuentra ninguna cláusula que pueda unificarse con color(chopper.symbol) clauses perro(chopper). Otro punto a tener en cuenta es que los hechos con la misma Relación y las reglas con igual cabeza van juntos.blanco). Para responder a una consulta. progenitor(Z. expresar las reglas bajo la siguiente estructura: hermano(X.Y):-progenitor(Z. La búsqueda comienza nuevamente desde el principio del programa. perro(sultan). hermano(romulo.merlina). Como hay más de una respuesta al llamado perro(X).X). Prolog logra un apareo con el primero de los hechos que define a perro. Veamos su funcionamiento mediante un ejemplo: predicates gusta(symbol. Prolog coloca una marca en el hecho perro(chopper). Así. la próxima subconsulta a satisfacer es color(X. unos a continuación de los otros: clauses varon(romulo). Logra el apareo con el hecho perro(sultan) y unifica la variable X con sultan. gusta(marcos. Esto es. Se origina una nueva búsqueda desde el comienzo del programa.Y) if progenitor(Z. color(sultan. ave) pero no puede unificarse puesto que el valor de X no coincide con gorrion. En este caso. debido a que hay más de una cláusula que define a vuelo. Como la variable Cual del goal externo había sido unificada con la variable X en la cabeza de la regla. tiene_alas(avion).ave) da comienzo a una nueva búsqueda (desde el comienzo) pero con la variable X unificada con avion.Apunte de Paradigma Lógico Paradigmas de Programación Prolog busca satisfacerlo desde el comienzo del programa. En cambio. Prolog hubiera seguido trabajando para encontrar otras posibles soluciones.ave) se aparea con es(X. Prolog logra unificar vuela(X) con el primer hecho definido. tiene_alas(gaviota). vuela(gaviota). tiene_plumas(gaviota). debajo se mostrará la cláusula con la que se unificó.ave) sí puede hacerlo porque Z es una variable aún 14 . Esta vez se logra la unificación para esta subconsulta. Prolog pone allí una marca. El hecho es(gorrion. El árbol ahora se encuentra así: vuela(X) es(X. el árbol consiste en dos subconsultas insatisfechas: vuela(X) es(X.ave) vuela(avion) La variable X se unifica con el valor avion.ave). El llamado es(X. Árbol de objetivos La búsqueda de una solución puede representarse mediante un árbol.En los pasos siguientes las subconsultas satisfechas serán marcadas en el árbol mediante subrayado. Prolog tomará cada subgoal en orden de aparición buscando una respuesta que satisfaga al conjunto.ave) if tiene_alas(Z) and tiene_plumas(Z).symbol) clauses vuela(avion). Las dos subconsultas de la regla fueron cumplidas al tener la variable X unificada con sultan. es(gorrion. Veamos el siguiente ejemplo: predicates vuela(symbol) tiene_alas(symbol) tiene_plumas(symbol) es(symbol. la regla es(Z. es(Z. Prolog dará la solución: Cual=sultan 1 Solution De haber quedado marcas pendientes. Este goal es compuesto.ave) .ave). y trata de satisfacer la próxima subconsulta. Al comenzar. Supongamos el goal externo: vuela(X) and es(X. Por este camino. Prolog encuentra un nuevo hecho y logra la unificación entre tiene_alas(Z) y tiene_alas(avion). El árbol queda de esta manera: vuela(X) vuela(avion) es(X. En nuestro ejemplo. la subconsulta se unifica con la cabeza de dicha regla y su cuerpo constituye un nuevo conjunto de subconsultas a satisfacer. Prolog encontrará los hechos para aparear y unificar con cada subconsulta de la regla: 15 . vuela(X) vuela(avion) es(X. en este caso la única. X es liberada y por ende también Z.ave) como se explicó anteriormente: vuela(X) vuela(gaviota) es(X. Se liberan las variables que estaban unificadas desde entonces. quedando X unificada con el valor gaviota: vuela(X) es(X. Ésta se encuentra en vuela(avion). Prolog no encontró una solución.ave) Prolog buscará ahora responder a la subconsulta vuela(X).ave) tiene_plumas(Z) tiene_alas(Z) Prolog buscará ahora los hechos o reglas que puedan unificarse con ambas subconsultas. la cabeza de la misma falla también. Así. La unificación entre tiene_alas(Z) y tiene_alas(gaviota) falla puesto que Z está unificada por medio de X al valor avion. Es necesario generar un árbol para el nuevo camino. De esta manera.ave) es(Z.ave) vuela(gaviota) La subconsulta es(X. Pero aún tiene una marca pendiente. lo que le permitirá retroceder por el camino hasta la misma y comenzar uno nuevo desde allí.ave) es(Z.ave) vuelve a unificarse con la regla es(Z.Apunte de Paradigma Lógico Paradigmas de Programación sin valor. vuela(X) se unifica con vuela(gaviota). éste queda de la siguiente manera: vuela(X) es(X. Prolog vuelve entonces hasta la última marca colocada.ave) tiene_plumas(Z) tiene_alas(Z) Esta vez. único hecho del programa que define a tiene_plumas.ave) tiene_plumas(Z) FALLA tiene_alas(Z) tiene_alas(avion) Al no encontrarse una respuesta para la última subconsulta de la regla. buscando a partir de donde estaba la marca. Pero la siguiente subconsulta falla dado que Prolog no puede unificar tiene_plumas(Z) con tiene_plumas(gaviota).ave) es(Z. X).X) if gusta(X.Apunte de Paradigma Lógico Paradigmas de Programación vuela(X) vuela(gaviota) es(X. amigo(matias.X) if gusta(X.rock).!.futbol). le dice a Prolog que si ésta se satisface.futbol).ave) tiene_plumas(Z) tiene_plumas(gaviota) tiene_alas(Z) tiene_alas(gaviota) Las subconsultas iniciales vuela(X) y es(X. para c podrá buscar múltiples soluciones. gusta(carlos.Quien).symbol) chica(symbol) gusta(symbol) clauses amigo(matias. Si el programa no tuviera cuts. rel if d. Lo mismo sucede con los cuts siguientes. Ejemplo: predicates amigo(symbol. gusta(diego. por lo que la respuesta de Prolog será: X= gaviota 1 Solution Predicado cut ( ! ) Se lo utiliza para cortar el backtracking. chica(julia).X) if chica(X) and gusta(matias. Ejemplo: rel if a and b and ! and c. 16 . no busque otras soluciones. El haber atravezado un Cut.ave) es(Z. . gusta(matias. En cambio. chica(marina). la respuesta de Prolog sería: Quien=julia Quien=carlos Quien=diego 3 Solutions El cut en la primera cláusula que define a la relación amigo. Supongamos el objetivo (goal) interno: amigo(matias.. En este caso la segunda cláusula que define a rel sólo será evaluada en caso de que no se llegue a evaluar el cut en la primera.!. inhibe también la evaluación de otra cláusula que defina la misma relación. amigo(matias.rock).!.ave) fueron satisfechas y no quedan caminos pendientes hacia nuevas posibles soluciones.julia). Prohibe que las variables unificadas hasta el momento de su aparición puedan ser liberadas y vueltas a unificar en busca de nuevas soluciones.. Así indicamos al intérprete que solo queremos la primera solución que encuentre para las subconsultas a y b. fail. ¿Cómo funcionará el fail en este ejemplo? Como el predicado fail (produce siempre falla) no puede ser satisfecho nunca. hombre(cesar). En caso que en el ejemplo no figurara el fail. El mismo está formado por tres subconsultas. De esta manera.tomas). hombre(julio). Para definir quiénes son mujeres. persona(julio).Y). Predicado fail Se utiliza para forzar el backtracking.Apunte de Paradigma Lógico Paradigmas de Programación El backtracking se utilizará sólo hasta que una cláusula pueda ser satisfecha. persona(eva). persona(cesar). clauses hijo(sebastian. persona(amalia).symbol) goal hijo(X. no se produce el backtracking. Prolog se ve forzado a regresar.Y) mediante un goal interno devolverá como máximo una sola solución. la respuesta de Prolog será la siguiente: Quien=julia 1 Solution. El backtracking toma el mando y vuelve al último llamado realizado que pueda producir otra solución.X“\n”). ya que aparece como parte del programa. la respuesta sería: tomás es el padre de sebastián Ahora bien. hijo(claudia. Aquí se define un conjunto de nombres de personas y se indica cuáles de ellos son hombres. write(Y. por lo tanto se llega nuevamente al primer subgoal de la regla. Es importante aclarar que una vez que un goal interno fue completamente satisfecho. hijo(gaston. De esta manera Prolog producirá lo siguiente: tomás es el padre de sebastián mariano es el padre de claudia lucas es el padre de gastón Uso de cut seguido de fail Ejemplo. El predicado write no puede ofrecer nuevas soluciones. Se tiene la siguiente base de conocimientos en la sección clauses de un programa: persona(beatriz).“ es el padre de ” . Ejemplo: predicates hijo(symbol. En este caso el goal es interno.lucas). podría escribirse: 17 . persona(marta). Por este motivo. la llamada a padre(X.mariano). Apunte de Paradigma Lógico Paradigmas de Programación mujer(marta). La variable X se unifica con eva y. mujer(amalia).fail. político(X):-corrupto(X). Allí pone una marca puesto que hay otra cláusula que define a mujer. pero además no son corruptos político(X):-persona(X). Si la consulta fuera mujer(cesar). la respuesta será: false.. Ahora Prolog busca satisfacer las subconsultas de la regla.!. de este modo. El cuerpo de la regla. Luego Prolog lee el fail. así que Prolog puede seguir con la segunda cláusula que define a mujer mediante backtracking. mujer(eva).!. 18 . Analice por qué no habrá solución para el goal: mujer(Quien). Esto hace que la subconsulta falle y por lo tanto también falla la cabeza de la regla. el análisis sería el siguiente. puesto que responde a consultas de validación pero no de búsqueda. político(X):-persona(X). not corrupto(X). Prolog logra unificar la primer cláusula que define a mujer con mujer(cesar). De la misma manera podemos decir que político(X):-persona(X). Prolog no puede aparear mujer(cesar) con la segunda cláusula que define a mujer ya que el backtracking fue cortado por el cut. El uso de cut combinado con fail. Supongamos que queremos afirmar “los políticos son personas no corruptas”. lo que se traduciría como: “Una mujer es toda persona que no es hombre”. Prolog logra una unificación con la primer cláusula que define a mujer pero luego falla al intentar unificar hombre(eva) con algún hecho. Si los políticos son personas.fail. compuesto por la subconsulta persona(X). político(X):-persona(X). Continúa con la siguiente subconsulta que es un cut y siempre tiene éxito. la respuesta es: true. Equivalencia entre el not y el cut + fail La equivalencia entre el not y el uso combinado de cut y fail puede verse en el siguiente ejemplo. se unifica con persona(eva). Como no se logró una solución y el goal externo era una consulta de validación. La variable X queda unificada con el valor cesar. nos permite definir al predicado mujer de la siguiente manera: mujer(X) if hombre(X). mujer(beatriz). not corrupto(X). Aclaración: la utilización de este recurso es limitada. Este cut “congela” a las variables en el estado en que están y elimina las marcas de backtracking pendientes hasta el momento. Note que la falla ocurrió antes de leer el cut. mujer(X) if persona(X). Ante la consulta mujer(eva). Busca desde el comienzo y logra la unificación con hombre(cesar).. Apunte de Paradigma Lógico Paradigmas de Programación La forma de operar con el cut y fail es simplemente buscar la condición que no se deba cumplir (como si demostrara por el “absurdo”): en caso de que se cumpla la elimina de la solución y falla. Aquí se verá más claro que. aunque equivalentes. no devuelven el mismo resultado: político(Quien)? 19 . PROLOG me permite simplemente armar una relación que llamo factorial entre dos números). son simplemente parámetros que se envían.  No puedo llamar a una regla: factorial (N-1). (Factorial será un hecho o una regla que podrá estar en la base de conocimientos como verdadera o falsa). (etc. Este es uno de los primeros “inconvenientes” que presenta y es importante distinguir que en PROLOG la recursividad es probar múltiples veces que un hecho o regla se cumple. y que no existen las funciones o procedimientos a los que estamos acostumbrados.  Tampoco es posible generar una sentencia N = N –1 que sea válida (recordar página 14). y utilizar algunos conceptos de otra forma:  Recordemos que no hay funciones en PROLOG. nos quedaría algo así como: Factorial (N) Si N = 0 entonces Factorial = 1 Si N > 0 entonces Factorial = N * Factorial (N-1) Pese a que nadie discutiría la validez del pseudo-código escrito. int) clauses factorial (0. Por lo tanto. factorial (N. Como vimos anteriormente. El cut evita posteriores ingresos a la cláusula de abajo (también podría haber modificado la segunda regla para que pregunte por N distinto de cero: factorial (N. por lo tanto. Consideremos el ejemplo por antonomasia de la recursividad: el factorial. si factorial recibe un argumento y devuelve el factorial de ese número. el paradigma lógico sólo acepta hechos y reglas que pueden ser verdaderos o falsos. FN = N * FN1. es necesario introducirnos al paradigma lógico. que será el valor “devuelto” por el predicado. Veamos: en la primera línea de la sección clauses asocio que factorial de 0 devuelve 1 (esta asociación la hago en forma arbitraria y yo le doy el sentido. Conceptualmente la regla pide valores para determinar si se cumple o no. FN):. factorial(N1. FN):.N1 = N – 1. FN1). debemos armar variables temporales (N1 = N – 1) y luego pasarlas como argumentos a las sucesivas llamadas recursivas. Si implementáramos en un pseudo-código esta función. N1 = N – 1. el factorial en Prolog se ve adaptado de la siguiente manera: domains predicates factorial (int. 1):-!.N > 0. Es importante recalcar esta diferencia porque de esta manera comprenderemos el paradigma en el que nos encontramos. Siempre que se quiera trasladar una función a este paradigma se debe agregar un argumento más. ya que las reglas tienen argumentos que no se evalúan como si fueran funciones. necesitaremos 2 argumentos: uno de entrada y otro de salida.Apunte de Paradigma Lógico Paradigmas de Programación Recursividad La recursividad dentro de este paradigma tiene aristas interesantes que lo diferencian de los otros y que trataremos de desarrollar en este apartado.)) 20 . Bajo este esquema. y es aquí donde se unifican otras variables: 21 . ejecutamos el goal: factorial (N1. FN1). con el valor devuelto de FN1. con N1 = 1. FN1). Todas las variables unificadas. ingresamos en la segunda cláusula (en la primera no coinciden los patrones para los argumentos. Intentaremos graficarlo para mostrarlo más claramente: Nivel Nivel 0 1 N=2 X = FN = ¿? N1 = 1 FN1 = ¿? N=1 FN = ¿? N1 FN1 Fig. donde el 0 es el que marcará el inicio de la recursividad. FN1) y finalmente. buscaremos hallar el factorial de 2: factorial (2. por lo tanto es una incógnita que debo resolver). Recordemos que la cláusula trace al comienzo de cualquier programa (antes de la sección domains) permite hacer el mismo seguimiento que el que haremos a continuación. En este momento es importante remarcar de qué manera trabaja PROLOG con la recursividad. Cuando PROLOG pida el objetivo. que indicará el valor de esta “función”. y así sucesivamente. y se verá solapado por el conjunto de variables que esté en el nivel 1. Para ello llama ahora recursivamente a factorial (N1. PROLOG sigue intentando cumplir el objetivo. Por lo tanto. sino que se almacenan en una pila o stack. N1 = N – 1 = 2 – 1 = 1 (se produce una asignación. y recibiré además un valor para FN1 (que está aún sin ligar. Entonces hacemos el matching correspondiente: factorial (N. En la siguiente llamada recursiva. ya que N1 estaba indeterminada). FN) donde N = 2. N1 = N – 1 Luego llamo para comprobar que la regla factorial se cumpla para N – 1 (así es como piensa PROLOG). y sus valores no se pierden. es realizar una prueba de escritorio. utilizo dos argumentos: el primero es un contador. Pero como no puedo llamar a factorial (N-1).Apunte de Paradigma Lógico Paradigmas de Programación En la segunda. y resuelvo la identidad para FN. factorial(N1. X)? La unificación de argumentos nos lleva a la segunda cláusula. ya que 0 <> 1). quedan suspendidas a un segundo plano. FN = X = ?. y el segundo un acumulador. a la que unifico con N – 1 y la llamo N1.1: primera llamada recursiva. Como todas las cláusulas anteriores se cumplían. A cada stack con sus correspondientes variables le asignaremos un nivel que irá desde el 0 en adelante. primero debo guardarlo en una variable auxiliar. Entendiendo por dentro a PROLOG La mejor manera de comprender cómo va unificando las variables el PROLOG. aplico FN = N * FN1. y PROLOG encontró la solución para factorial (1. Pero es importante recordar que FN en el nivel 1. Ahora debe volver al nivel anterior. FN1). es en realidad FN1 en el nivel 0: la llamada se hizo a factorial (N1. FN1 resuelve su identidad de esta manera: vale 1 y el nivel 1 puede continuar para probar que factorial (1. Esto es lo más importante de comprender para entender por qué no son las mismas variables para PROLOG.2: Segunda llamada recursiva Lo que sucede aquí es que al llamar a factorial (0. y corta la búsqueda de soluciones alternativas (evita así ingresar en la segunda cláusula y continuar llamando a factorial con números negativos). 1) y corte (!) Fig. que se puede apreciar en la figura 2. 1). esta vez con N1 = 0. Encuentra el hecho factorial (0.Apunte de Paradigma Lógico Paradigmas de Programación N1 del nivel 0 pasa a ser N del nivel 1. FN) del nivel 1. N = 1. Entonces. y FN1 = 1. PROLOG guarda el juego de variables y unifica los argumentos que conoce. se liberan las variables utilizadas en el nivel 2 y PROLOG unifica: FN = N * FN1 En el nivel 1. La figura 3 ilustra este hecho relevante: 0 Nivel 1 N=1 N1 = 0 FN = 1 FN1 = 1 Nivel N=2 X = FN = ¿? N1 = 1 FN1 = 1 22 . y la unificación de argumentos dio factorial (N. y por qué funciona entonces la asignación N1 = N – 1 nuevamente. FN1). llamamos a factorial (N1. Una vez más. por lo tanto FN resuelve su identidad también (= 1). unificando todas las variables que estaban sin determinar. FN1) se corta la recursividad: se produce un pequeño paso de unificación en el nivel 2. Entonces. Nivel 0 (solapado) 1 N=2 X=F N1 = FN1 Nivel Nivel 2 N=1 FN = ¿? N1 = 0 FN1 = ¿? factorial (0. FN). FN) se cumple. y FN1 del nivel 0 pasa a ser FN del nivel 1 (ver ambas flechas de la figura 1). 707). El problema parece reducirse a una regla recursiva. por lo tanto. 280). que se llame repetidas veces. distancia(buenos_aires. chascomus. Una vez más. recordamos que no hay funciones en PROLOG. 320). Buenos Aires. nos detendremos en particular en un ejemplo más: el problema de las distancias entre ciudades. Lo que debemos construir es una regla que se llame ruta. mar_del_plata. distancia(chascomus. Si tomamos en cuenta que las ciudades están conectadas por una única ruta serial. que determine la distancia. Chascomús y Mar del Plata. 23 . Distancia). Ciudad2. Distancia):. distancia(cordoba. podemos armar un sistema que calculara todas las distancias entre las ciudades. !. Veamos: los hechos son tres a los que recurrimos como datos. 1) Conozco la distancia  hay ruta entre dos ciudades A y B ruta(Ciudad1. 707 Córdoba 280 Buenos Aires 320 Chascomús Mar del Plata ¿Cómo podemos saber la distancia entre una ciudad A y otra B? Si partimos de la ciudad A y llegamos a la B (distancia conocida). que es lo que PROLOG termina devolviendo a la pantalla: X = 2 1 Solution Otros problemas recursivos Muchos son los casos que nos llevan a problemas recursivos. Ciudad2. al final de este apunte encontrarán ejercicios que servirán de práctica para ello.distancia(Ciudad1. Entonces. sólo resta buscar el valor de FN (para el nivel 0.Apunte de Paradigma Lógico Paradigmas de Programación Fig. el dato que devuelve la distancia debe ser el tercer parámetro del hecho.3: Regreso de la llamada recursiva del nivel 1 al nivel 0. buenos_aires. ya que todas las variables del nivel 1 se liberaron): FN = N * FN1 FN = 2 * 1 = 2 y se unifica a X. Sean cuatro ciudades cualesquiera: elegiremos Córdoba. o Si a través de alguna ciudad intermedia X llegamos a la B. Distancia = Distancia1 + Distancia2. Ciudad2. Distancia2). Distancia) de la siguiente manera: Ciudad1 = cordoba Ciudad2 = mar_del_plata Distancia = X Se cumplirá si se cumple distancia(Ciudad1. kilometros) clauses distancia(cordoba. ciudad. Entonces debo comprobar ruta (buenos_aires. El programa queda armado de la siguiente manera: domains ciudad = symbol kilometros = integer predicates distancia(ciudad. mar_del_plata. 2) Si no conozco la distancia  puedo partir de A y llegar a distintas ciudades. X)? La primera regla ruta no se cumple ya que no hay una distancia calculada entre ambas ciudades.distancia(Ciudad1. donde X se iguala a 280 y se lo envía a ruta para resolver la identidad. Distancia). CiudadIntermedia. ¿Hay alguna ciudad a la que se llegue desde Córdoba? Sí. Aquí necesitamos un stack para guardar las variables que estarán en segundo plano y tomar un nuevo juego: Nivel 0 (solapado) Nivel 1 Ciudad1 = buenos_aires Ciudad2 =mar_del_plata Distancia = ¿? Ciudad1 = cordoba Ciudad2 = mar_del_plata Distancia = X = ¿? CiudadIntermedia = buenos_aires Distancia1 = 707 Distancia2 = ¿? 24 . Veamos un caso concreto: goal: ruta(cordoba. Ciudad2. ruta(Ciudad1. ruta (CiudadIntermedia. ruta(Ciudad1. CiudadIntermedia.Apunte de Paradigma Lógico Paradigmas de Programación En este caso el “matcheo” se hace automáticamente. mar_del_plata. X). si quiero conocer la distancia entre Chascomús y Mar del Plata busco el hecho distancia (chascomus. distancia(buenos_aires. !. Distancia = Distancia1 + Distancia2. ciudad. 707). Distancia1). Distancia1). buenos_aires. CiudadIntermedia se iguala a buenos_aires. Distancia):. chascomus. Distancia2). hasta llegar a una ciudad X que por esa haya una ruta directa a B.ruta(Ciudad1. distancia(chascomus. Ciudad2. mar_del_plata. Distancia2). Ciudad2. Esto nos lleva a matchear: ruta (Ciudad1. CiudadIntermedia. Ciudad2. ruta(Ciudad1. Ciudad2. En este caso tenemos que aplicar recursivamente la regla ruta hasta llegar a la ciudad previa al destino que queremos alcanzar. Distancia):. kilometros) ruta(ciudad. Ciudad2. 280). En Distancia2 almaceno el valor 707. Distancia):. 320).distancia(Ciudad1. mar_del_plata. Distancia1). distancia (CiudadIntermedia. Aplico el mismo método. no hay distancia calculada entre cordoba y buenos_aires. Distancia2) se cumple ya que hay distancia(chascomus. Distancia se asigna a 280 + 320 = 600 ya que no tenía ningún valor ligado. Distancia2) : Nivel 0 (solapado) Nivel 1 Ciudad1 Ciudad2 Distancia CiudadInte Distancia1 Distancia2 Ciudad1 = buenos_aires Ciudad2 = mar_del_plata Distancia = ¿? CiudadIntermedia = chascomus Distancia1 = 280 Distancia2 = ¿? Nivel 2 Ciudad1 = chascomus Ciudad2 = mar_del_plata Distancia = ¿? Entonces encuentro que ruta(chascomus. 320). mar_del_plata. que era nuestro verdadero objetivo. Distancia2 entre chascomus y mar_del_plata. Desde el nivel 1 hacemos Distancia = Distancia1 + Distancia2: Nivel 0 (solapado) Nivel 1 Ciudad1 Ciudad2 Distancia CiudadInte Distancia1 Distancia2 Ciudad1 = buenos_aires Ciudad2 = mar_del_plata Distancia = ¿? CiudadIntermedia = chascomus Distancia1 = 280 Distancia2 =320 Distancia1 era la distancia entre buenos_aires y chascomus. Distancia1 = 280 y llamando recursivamente a ruta(chascomus.Apunte de Paradigma Lógico Paradigmas de Programación Una vez más. mar_del_plata. Logramos determinar la distancia entre buenos_aires y chascomus y lo enviamos al nivel 0: Nivel 0 (solapado) Ciudad1 = cordoba Ciudad2 = mar_del_plata Distancia = X = ¿? CiudadIntermedia = buenos_aires Distancia1 = 707 Distancia2 =600 25 . mar_del_plata. El cut previó salidas imprevistas por culpa del backtracking en cada llamada recursiva. encontrando a CiudadIntermedia = chascomus. Entonces desaparece el nivel 2 y podemos calcular las distancias correspondientes en cada uno de los niveles. (La comprobación queda a cargo del lector)  La segunda plantea soluciones más complejas que exceden el temario de la cátedra. 26 . pero como simple enunciado. De todas maneras. si sabemos que de cordoba a buenos aires hay 707 km. que era nuestra incógnita. Entonces asignamos Distancia (que en el nivel 0 no está ligado a ningún valor): a 707 + 600 = 1307 km. lo mejor a la hora de comprender soluciones en problemas recursivos de PROLOG es hacer pruebas de escritorio que contrasten con la lógica descripta de la aplicación en cuestión. qué ocurriría si en lugar de una ruta serial se cruzaran rutas alternativas uniendo varios puntos del país. podemos probar invirtiendo los argumentos sólo en el antecedente y dejando el consecuente exactamente igual para ambas reglas ruta. y de buenos aires y mar_del_plata 600. PROLOG devuelve. y logramos unificarlo a X.Apunte de Paradigma Lógico Paradigmas de Programación Todo parece más fácil. finalmente: X=1307 1 Solution Podemos agregar dos complicaciones al presente ejercicio:  La primera es fácil de reconocer: ¿cómo hacer para recorrer el camino inverso? Para viajar desde mar_del_plata a cordoba habría que modificar la aplicación: no es demasiado complejo. Sería interesante hallar el camino más corto entre dos ciudades. c]] equivale a [a|[b|[c]]] que equivale a [a|[b|[c|[]]]] La siguiente es una definición del tipo de dato lista: lista( [ ] ). es necesario un símbolo constante para terminar la recursión. De esto se deduce que una lista es una lista vacía o la construcción de un par donde la primera parte es un elemento y la segunda es una lista. una lista compuesta por los símbolos a. Para las listas. [a. que es indivisible. c]. podemos descomponer una lista en forma recursiva en cabeza y cola. esta es la lista vacía que se denomina “nil” y se denota [ ]. el símbolo “|” es el operador de concatenación. el segundo argumento es recursivamente el resto de la lista. que no es lo mismo que el elemento que contiene. hasta llegar a la lista vacía. y en consecuencia [a|[b.Apunte de Paradigma Lógico Paradigmas de Programación Uso de listas El primer argumento de una lista es un elemento. c] equivale a [a|[b. igual que en los naturales. X es la cabeza de lista e Y es la cola. También se necesita un functor binario que en el caso de Prolog se escribe así: [X | Y]. y se representa lista a lista b lista c [] Una lista compuesta por un solo elemento (el 1) se escribe [1]. lista( [ Cabeza | Cola ] ) :. Ejemplo: domains 27 . El uso de listas es útil para tratar con una cantidad de elementos desconocida a la hora de implementar una solución.c]]. b y c se escribe: [a. ya que es una estructura compuesta por: lista 1 [] De esta manera. b. b. Así.lista( Cola ). Observe que la cabeza de la lista no queda unificada a ninguna variable puesto que no es necesario conocer su valor. [ _ | Z ] ). [ X | _ ] ) es un hecho Prolog nos devuelve como respuesta True. Prolog repetirá los pasos arriba mencionados. Utilizando el hecho write (que muestra por pantalla el argumento que se envía) y llamándose recursivamente. en este caso Prolog si logra la unificación porque X coincide con la cabeza de la lista. El segundo. X=3. La única manera posible de lograr esto es usando “_” en lugar de una variable (Prolog no permite utilizar variables que luego no van a ser usadas). se va recorriendo la lista de a un elemento. 3 ] ) . [ 1 . imprimir_lista([Cabeza|Cola]):-write(Cabeza). [ 2 . 8 ] ). [ X | _ ] ). quedando X unificada con 1 y Z con la cola de la lista. y como este es distinto de 1 la unificación falla. y Cola es una lista compuesta por enteros. [ X | _ ] ). Aquí se define una lista de enteros. El primer ejemplo que veremos es cómo recorrer una lista para que imprima sus elementos: domains lista=integer* predicates imprimir_lista(lista) clauses imprimir_lista([]). que devolverá X=1. 1 . y entonces como miembro( X .miembro( X .[ _ | Z ] ):. [ 2 . Z ). 8 ] ) con miembro( X . Prolog primero aparea miembro( 1 . en este caso la unificación es exitosa. por ese motivo. 8 ]. Como normalmente ocurre podemos darle varios usos a este programa. Podemos pedir: 28 . unifica X con 1 y realiza la comparación de X con el primer elemento de la lista. nl. que es la cabeza que ha sido descartada. Como miembro( X . [ _ | Z ] ) es la cabeza de una regla. Z ).lista) clauses miembro( X . El más simple es verificar si un elemento está en una lista (o sea la consulta hecha arriba). hallar los elementos de una lista: miembro( X . 8 ] ) con miembro( X . Si se le hiciera la consulta (goal): miembro( 1 . 1 .Apunte de Paradigma Lógico Paradigmas de Programación lista= elemento* elemento= integer predicates miembro(elemento. el llamado a imprimir_lista tiene como argumento otra lista y no es necesario utilizar los corchetes para separar los elementos. Nótese que Cabeza es un integer. Otros ejercicios con listas Pero la mayoría de los ejercicios con listas consisten en recorrer la lista (al mismo tiempo que se va extrayendo la cabeza) y operar con cada uno de los elementos. 1 . Prolog procederá a verificar la subconsulta miembro( X . imprimir_lista(Cola). Luego Prolog aparea miembro( 1 . pero con un elemento menos en la lista. miembro( X . [ 2 . o sea [ 1 . Como write siempre devuelve verdadero y recorrimos la lista hasta llegar a la cláusula con la lista vacía (que es nuestra condición de corte). 0). Sí entra por la segunda cláusula. así que debemos generar una nueva variable y ligarle el valor de Cont + 1.5]) que devuelva 5 2 4 1 true Tomando el esquema original del primer programa. Hagamos una vez más la prueba de escritorio para ver cómo se asignan los argumentos al trabajar con listas. Lo que sí necesitamos es la cola de la lista para seguir la iteración hasta encontrar la condición de corte: una vez más la lista vacía (y la longitud de una lista vacía –cero. contador) clauses contar_elementos([].se define como un hecho).2]. Ya que no tenemos funciones que devuelvan enteros. 29 .4. Ejercicio: Modifique el programa para que emita por pantalla los elementos de una lista en orden inverso. El único concepto nuevo que aparece aquí es el de la variable anónima: no podemos definir una variable X si después no la utilizamos en alguna operación.2.2] no se puede unificar con la lista vacía no se toma en consideración el primer hecho. Dado que [1. con un poco de suerte: 2 4 6 true El “true” final nos recuerda que. donde se produce el siguiente matching: Nivel 0 [ _ |Cola] = [1.Apunte de Paradigma Lógico imprimir_lista([2. Supongamos el objetivo: contar_elementos([1. El programa finalmente nos queda: domains lista=integer* contador=integer predicates contar_elementos(lista. Cont = Cont + 1 siempre es falso en PROLOG. contar_elementos(Cola. y Cola del nivel 0 es una nueva lista abierta en cabeza y cola para el nivel 1. el objetivo de cualquier aplicación PROLOG es determinar si las cláusulas se cumplen o no en una base de conocimientos dada. más allá del efecto procedural que querramos darle. Cont1). Ejemplo: imprimir_reverso ([1. X)? No conocemos la longitud de la lista. Por lo tanto. resolvimos el problema.4. el símbolo underscore ( _ ) significa que el valor de la cabeza será descartado dentro de esta regla. necesitaremos un argumento adicional para utilizarlo como contador. Y como ya sabemos. contar_elementos([_|Cola].6]) Paradigmas de Programación lo que nos devolverá. debemos recorrer sucesivamente cada elemento y así incrementar algún contador. aplicaremos algunas operaciones sobre las listas: si queremos conocer la cantidad de elementos que tiene una lista. Cont):Cont = Cont1 + 1. 2]  Cola = [2] Cont = ¿? Cont1 = ¿? La primera llamada recursiva hace que PROLOG guarde el nivel 0 en el stack o pila y realice el pasaje de argumentos. Entonces Cont1 del nivel 0 se matchea con Cont del nivel 1. que es el argumento X. Se guardan las variables del nivel 1 y se pasa a un breve nivel 2: allí el segundo argumento vale 0 (la longitud de una lista vacía) y se logra resolver el valor de Cont para el nivel 1: Cont = Cont1 + 1 = 0 + 1 = 1. con la cola vacía. Veamos: 30 . 2. Cont):. En lugar de usar un contador. Cont1). El resultado final aparece en la ventana goal de PROLOG: 2 1 Solution Inversibilidad de reglas: ¿qué sucede si trata de ejecutar el goal contar_elementos ( X. es decir. 2]  Cola = [2] Cont = ¿? Cont1 = 1 Nivel 0 Ahora que resolvimos Cont para el nivel 1. aunque ésta será solamente una sutil diferencia técnica. 3)? ¿Se pueden alterar los argumentos como incógnita? Sumando listas Ahora veremos el mismo ejercicio anterior. se vuelve a producir una llamada recursiva: contar_elementos. adaptado para que sume los elementos de una lista de enteros.contar_elementos(Cola. Cont = Cont1 + 1. generamos un acumulador. Cont1 vuelve con valor 1 y la resolución es simple: Cont vale Cont1 + 1. Nivel 1 [ _ |Cola] = [2]  Cola = [] Cont = 1 [ _ |Cola] = [1. volvemos al programa original en el nivel 0: contar_elementos([_|Cola].Apunte de Paradigma Lógico Paradigmas de Programación Nivel 1 [ _ |Cola] = [2]  Cola = [] Cont = ¿? Entonces. 4.6]. llenaremos Acum sucesivamente con: 0 (cuando hayamos vaciado la lista). Ejemplo: si tenemos la lista [1.2. integer) clauses sumar_elementos_par([].Cabeza|Cola]. Acum1).5. 6. Concatenación de listas En general. sumar_elementos([Cabeza|Cola].sumar_elementos(Cola. Utilizando un ejemplo práctico.3. sumar_elementos_par([_.Apunte de Paradigma Lógico Paradigmas de Programación domains lista=integer* predicates sumar_elementos(lista.4.3. 17)? ¿Se pueden invertir las incógnitas de esta regla? Analice el resultado que devuelve PROLOG. Pero como ejercicio. asignamos la cabeza a una variable (casualmente llamada Cabeza). Acum = Acum1 + Cabeza. Ejercicio: 1) realice el mismo ejercicio que sume los elementos que están en la posición impar de una lista que siempre contendrá una cantidad par de elementos. en lugar de la variable anónima.6] 31 . los ejercicios de aplicación utilizan las técnicas arriba descriptas. Acum):sumar_elementos_par(Cola. Acum):. [2. 2) Modifique ambos programas para que acepte una lista de cualquier longitud (par o impar). X) deseamos que PROLOG nos devuelva X = [1. hallar C tal que sea A + B. dado el goal: concat([1.6]. 3) ¿Qué sucede si pedimos sumar_elementos_par(X. para luego sumarla al acumulador.4. 0). integer) clauses sumar_elementos([]. la solución es sencilla. resulta interesante el método de concatenación de dos listas: sean una lista A y otra B. Acum = Acum1 + Cabeza. En realidad el acumulador se va completando de atrás para adelante. 0). 10 y 11.5]. En este caso. ¿Qué sucede si queremos sumar los elementos que están en la posición par de una lista? Siempre que nos garanticen que habrá una cantidad de elementos par para una lista. Así vamos sumando los elementos a medida que la recorremos. Acum1). apelaremos a la variable anónima para descartar el primer elemento de la lista (que serán los elementos que se ubiquen en una posición impar) y tomar sólo el siguiente: domains lista=integer* predicates sumar_elementos_par(lista. lista. X)? y aplicamos el seguimiento correspondiente. Lista3). 2. que no es otra cosa que [1.2. Así.4] y entonces concat devuelve [Cabeza|Lista3]. veremos que tras dos llamadas recursivas. con cada llamada recursiva que se cierra. 2) Una vez vaciada la primera lista. Lista3 vale [3.4] Lista3 = ¿? Nivel 1 Lista1 = [] Cabeza = 3 Lista2 = [2.4] Lista3 = [2. [Cabeza|Lista3]):. la primera lista queda vacía.concat(Lista1. se concatena al principio de la tercera lista cada elemento de la primera.3. Lista2. Realicemos una breve prueba de escritorio: si queremos ejecutar concat([1. [2. Lista2. “agregándole” cada cabeza de la lista 1 a la tercera lista. concat([Cabeza|Lista1].2. En el nivel 0. al ser incógnita. se unificará directamente) 3) Volver recursivamente con cada llamada. 32 . asignar la segunda lista a la tercera (que.4] A partir de aquí la técnica “agrega” la Cabeza a la Lista3: concat devuelve [Cabeza|Lista3] que es igual a [3. El programa queda finalmente: domains lista=integer* predicates concat(lista.4] en el nivel 1: Nivel 0 (solapado) Lista1 = [3] Cabeza = 1 Lista2 = [2. Lista2). 4]. Entonces la tercera lista se iguala a Lista2 = [2.3]. lista) clauses concat([]. Por ello es muy importante tener en claro el manejo de recursividad para llegar a soluciones adecuadas en el trabajo con listas.Apunte de Paradigma Lógico Paradigmas de Programación La técnica a utilizar será la siguiente: 1) Recorrer la lista 1 hasta vaciarla. Lista2.4].4]. Y=pericles.pericles) Quien=la_abuela.Familia Adams. 4.Colores. tio_cosa y la_abuela. X=homero. La Familia Adams esta compuesta por homero.Listas 8. X=tio_lucas.homero) hija(Quien. Homero es hermano de tio_lucas y de tio_cosa. X=tio_lucas. abuela(Quien.Canales. Morticia es esposa de homero y con ella ha tenido dos hijos: pericles y merlina. X=merlina. 1. pericles. hermana(X.Autómata finito no determinístico. (el resultado duplicado se debe a que merlina es hermana de pericles tanto por su madre como por su padre). Y=merlina.Prendas.Apunte de Paradigma Lógico Paradigmas de Programación Ejercicios de Aplicación.Y) X=merlina. X=tio_cosa.pericles) tio(X. Y=merlina. 5. 1. tio_lucas. Y=pericles.Y) 33 . X=tio_cosa. Quien=merlina. Y=pericles.homero) padre(X. merlina. Y=pericles. morticia. Defina un programa Prolog que contenga estas relaciones y que pueda ser consultado del siguiente modo: Respuesta: Verdadero.Arañas. 6. Consulta: hijo(pericles. 2. 7.Familia Adams. todos ellos son hijos de la_abuela. 3.Ojos. a) Construir un programa donde los hechos sólo sean predicados del tipo canal(nombre) y c_aire(nombre). ATC. Volver. Dado el siguiente programa: 34 . Dadas las siguientes relaciones: nombre Martín Diana Lucas Cecilia Soledad color negro verde azul blanco violeta prenda pantalón pantalón camisa bufanda saco color azul negro verde violeta azul y sabiendo que una persona usará determinada prenda si es del color que le gusta.. 5-Colores. MTV.. b) Modificar el programa para que al ejecutarlo muestre una lista con el siguiente formato: ser tiene n patas . 3. ATC. diseñar un programa que responda a un goal externo qué prendas usará una persona. . 4. Los insectos tienen seis patas. Dados los siguientes datos: Canales de televisión: América. Fox.Arañas.Prendas. Telefe.Apunte de Paradigma Lógico Paradigmas de Programación 2. a) Hacer un programa que responda cuántas patas tiene uno de los seres de la tabla. Dada la siguiente tabla: clase ser tarántula hormiga mosca viuda negra avispa alacrán arácnido insecto * * * * * * Los arácnidos tienen ocho patas.Canales. b) Establecer las reglas necesarias para responder al goal externo: c_cable(fox).. Canales de aire: América.Telefe. Cablín.. Manuel. utilizando la regla secund(X) como una de sus instancias.azules) ojos(maria.blanco). María.Un color es secundario si se forma con dos colores primarios. primario(azul). Juan. Ambos tienen el pelo negro. tiene 13.rojo. Todo alumno que no tenga 12 años. primario(amarillo).amarillo). Sofía tiene el color de ojos del que tiene el pelo rubio. Manuel y Paula tienen 12 años. formado_por(gris.Y). cuando el primero se forma con dos colores primarios entre los cuales el color “y” no se encuentra. Pablo tiene los ojos marrones y el pelo rubio.azul).6.color) edad(pablo. Sofía y Pablo son alumnos de séptimo grado. María tiene el color de ojos que tiene Juan. 7-Autómata Finito no Determinístico Construir un programa prolog que acepte la siguiente cadena (aab)*(ba+ ab) 3 a 2 7 35 5 b 4 a b . formado_por(naranja.Un color “x” es complementario de un color primario “y”. formado_por(celeste.blanco). formado_por(violeta.Color) ojos(Quien. a) Diseñar la regla secund(X). Diseñar un programa capaz de responder a los siguientes goals externos: ojos(sofia.color) clauses primario(rojo).12) edad(juan.amarillo). Juan tiene los ojos azules y Manuel los tiene verdes.Ojos. b) Diseñar la regla comple(X.azul. . .azul.Apunte de Paradigma Lógico Paradigmas de Programación domains color=symbol predicates primario(color) formado_por(color.negro.rojo.color) secund(color) comple(color.13) Aclaración: no está permitido definir los hechos haciendo algún tipo de inferencia. formado_por(verde. 3) se puede acceder a través de una movida silenciosa a un estado de aceptación. 2) se puede acceder mediante una transicion a un estado de aceptación.indica el estado inicial. Definir los predicados: acepta(nodo.nodo2) Una cadena será aceptada si 1) se está en un nodo final y la cadena es vacía.Apunte de Paradigma Lógico Paradigmas de Programación a b a null 1 Teniendo en cuenta que el signo + indica los estados finales y el signo .cadena) final(nodo) trans(nodo1. 6 a 36 . nodo2) silenciosa(nodo1.letra. NOTA: Este ejercicio fue copiado del apunte Prolog de Miguel Angel Gionco. tio_lucas).nombre) hermana(nombre.prenda. tio(X. 37 .Y). gusta(cecilia. progenitor(la_abuela. progenitor(homero.homero). mujer(morticia). progenitor(morticia.Y):-progenitor(Z.Y):-progenitor(Y.Y):-progenitor(X.verde).progenitor(Z.Z). hermana(X.X). progenitor(homero.tio_cosa). gusta(lucas.color=symbol predicates gusta(nombre. progenitor(la_abuela.Y). abuela(X.nombre) padre(nombre.varon(X).X<>Y.varon(X).pericles).merlina).progenitor(Z.color) color(prenda.color) usa(nombre.X).varon(X). padre(X.X).Y).X).pericles).progenitor(Z. hermano(X.nombre) tio(nombre.nombre) hijo(nombre. progenitor(morticia. gusta(diana. progenitor(la_abuela.Y):-progenitor(Y.nombre) madre(nombre.Y). madre(X. varon(pericles). varon(tio_lucas).mujer(X).Apunte de Paradigma Lógico Paradigmas de Programación Soluciones: 1) domains nom=symbol predicates varon(nombre) mujer(nombre) progenitor(nombre. mujer(la_abuela).Y):-hermano(X.prenda) clauses gusta(martin.Y):-madre(X. hija(X.Y):-progenitor(X.negro).nombre) clauses varon(homero).progenitor(Z. mujer(merlina).mujer(X).mujer(X).azul).Z).nombre) abuela(nombre.X<>Y.Y):-progenitor(Z.nombre) hija(nombre. 2) domains nombre.blanco).merlina).Y).Y). varon(tio_cosa). hijo(X. 4) domains nombre=symbol predicates canal(nombre) c_aire(nombre) c_cable(nombre) clauses canal(america). canal(volver). color(pantalon. aracnido(alacran). c_cable(X):.cant) clauses aracnido(tarantula). canal(mtv). canal(fox).Z) and color(Y.Apunte de Paradigma Lógico Paradigmas de Programación gusta(soledad.verde).fail. c_aire(atc).violeta). canal(atc). b) Agregar entre predicates y clauses: goal patas(N. color(pantalon. color(camisa. c_aire(america).6):-insecto(X).azul).Y) if gusta(X. patas(X.violeta). insecto(avispa).8):-aracnido(X). aracnido(viuda_negra).Z).negro). color(saco. canal(cablin).M.fail." patas\n").M).c_aire(X). 38 . insecto(mosca). 3)a) domains nom=symbol cant=integer predicates aracnido(nom) insecto(nom) patas(nom. write(N.azul). patas(X. insecto(hormiga).!. c_aire(telefe). usa(X. canal(telefe). color(bufanda." tiene ". negro). ojos(sofia.W).formado_por(X. alumno(pablo).Z.nodo) clauses 39 . edad(sofia.Z).Y.13).Y<>W. edad(X. edad(X.num) clauses alumno(juan). ojos(marcia. alumno(marcia). ojos(manuel. primario(Y). pelo(manuel.13). alumno(manuel). secund(X).X):-pelo(Y.marrones).cadena) silenciosa(nodo.Apunte de Paradigma Lógico Paradigmas de Programación c_cable(X):. ojos(pablo.X).Y):. complem(X. alumno(sofia).azules).letra.verdes).rubio). 7) domains nodo=symbol cadena=letra* letra=symbol predicates final(nodo) trans(nodo.ojos(Y. Y<>Z. ojos(juan.fail. primario(Y). primario(Z).14):-edad(X.rubio).nodo) acepta(nodo.14):-alumno(X). pelo(juan. 5) Agregar en clauses las siguientes reglas: secund(X):.formado_por(X. pelo(pablo.negro). 6) domains nombre.13).color) pelo(nombre.X).!.canal(X).color) edad(nombre.color=symbol num=integer predicates alumno(nombre) ojos(nombre. edad(manuel.X):-ojos(juan. trans(n4.[X|R]):. trans(n4. acepta(M.b. acepta(Nodo.n2). acepta(Nodo.M).b.Apunte de Paradigma Lógico Paradigmas de Programación final(n7). 40 . trans(n2.a. trans(n6.n4).a.n6).n5).R).n7). trans(n1.Nodo1).a.n7). trans(n5. acepta(N.Cadena).trans(N.a.a.b. silenciosa(n1.X.Cadena):-silenciosa(Nodo.n2). trans(n3.n4).acepta(Nodo1. [ ]):-final(Nodo).n3). trans(n4. armar un plantel de jugadores que actuaron en ambos conjuntos. sanlorenzo) Quienes=hrabina Quienes=ortiz Quienes=pogany Quienes=marangoni Quienes=acosta 5 Solutions Debe codificar la regla esta (AUXILIAR). sanlorenzo]). equipo. boca]). campaña(gorosito. univcatolica. Se tienen N urnas con X bolillas blancas y Y bolillas negras. boca. chacarita) False 2) Dados dos equipos. de sucesos posibles (todos) 41 . : intersección(Quienes. campaña(acosta. equipo) clauses campaña(hrabina. sanlorenzo]). [union. independiente. boca. [sanlorenzo. campaña(pogany. Se desea calcular la probabilidad de sacar de cada una de las N urnas 1 bolilla de color Z (Z puede ser blanca o negra). sanlorenzo. indicará si el jugador participó alguna vez de ambos planteles Ej. campaña(marangoni. sanlorenzo. : intersección(marangoni. huracan. [atlanta. sanlorenzo. de sucesos A P(suceso A) = cant. boca]). univcatolica]). Ej. domains lista_equipos=symbol* jugador. [sanlorenzo. [boca. huracan) True intersección(hrabina. campaña(ortiz. [huracan. campaña(barticiotto. boca. boca. sanlorenzo. lista_equipos) intersección(jugador. univchile]). atlanta. univcatolica. Para eso se sabe que: 2) cant. equipo=symbol predicates campaña(jugador.Apunte de Paradigma Lógico Paradigmas de Programación Ejercicios de aplicación El objetivo del problema es resolver la regla intersección: 1) Dado un jugador y dos equipos. independiente]). que indica si un equipo está en una lista de equipos. [huracan. lista_equipos) esta(equipo. que refleja la situación planteada. resultado). donde 'color' es el color de la bola de la que se quiere calcular la probabilidad.Apunte de Paradigma Lógico Paradigmas de Programación P(suceso A y suceso B) = P(A) * P(B) P(1 bol.  tiene más de 3 pagos rechazados en bancos  el ranking elaborado por los empleados (de 1 a 10) le da 5 o menos.  el promedio de ventas mensuales es menor a 4. y es poco confiable si una o 2 características están en rojo (digamos que es poco confiable por defecto). 'listaUrnas' es el conjunto de todas las urnas (identificadas por su número) que participan en el cálculo de la probabilidad. donde 'numero' indica el numero de urna. recepción de cheques diferidos. y 'resultado' (obviamente) es el resultado de calcular la probabilidad del suceso con las condiciones ya especificadas (tener en cuenta que puede devolver un n£mero real). listaBolillas). Se pide generar un programa COMPLETO (reglas y hechos) que permita consultar con el predicado prob para calcular la probabilidad de ocurrencia de 1 bolilla Z (blanca/negra) en las N urnas. es confiable si ninguna característica está en rojo. espococonfiable (cliente) y esnoconfiable (cliente). Dada la sgte estructura lógica. domains cliente = symbol caracteristica = symbol calificacion = symbol cantidad = real 42 . para resolver el problema. además de los 2 ya indicados. Nota: Incluir todos los hechos y reglas que se necesiten. Se basa en 4 características principales:  saldo actual de la cuenta corriente (saldo)  promedio de ventas mensuales (promedio)  pagos rechazados (rechazos)  ranking interno elaborado por los empleados (ranking) Las características se ponen en "rojo" si:  el saldo de la cuenta corriente supera los $2000. y 1 bol. listaUrnas. 3) Mi pequeño Veraz: La compañía productora de pirufios decide elaborar un ranking de clientes. resolver la regla confiabilidad(cliente. debiéndolos clasificar en "no confiables". lo cual le sirve para establecer límites de crédito.calificacion) y las reglas esconfiable(cliente). y 'listaBolillas' es el conjunto de todas las bolillas negras y blancas de esa urna. 2) predicado prob(color. Z urna 2 ) = P(U1) * P(U2) Además se sabe que existen los predicados: 1) urna(numero. "poco confiables" y "confiables". Un cliente no es confiable si 3 de las cuatro características están en "rojo". etc. entregas. Z urna 1. Z). X):. 'e']. enrojo enrojo enrojo enrojo 4) Dada ( saldo .'c'.X):. cantidad) esconfiable (cliente) espococonfiable (cliente) esnoconfiable (cliente) caract(cliente. 'x'. Variante: . predicates sinvocal (char*. Y. Y) :. (promedio. Z). 'x'. 'x'. X):. calificacion) poseecaracteristica( cliente.'c'. Armar la relación sinletras(string. 'x'.X > 2000.X <4.Apunte de Paradigma Lógico Paradigmas de Programación predicates confiabilidad (cliente. (rechazos. char.  Obtener la diferencia entre las posiciones pares y las impares ("componiendo" las reglas o sin utilizar variables anónimas). "devolver" la suma de las posiciones pares: domains listaint= integer * predicates sumapar(listaint. (ranking.caract (X. char* ). caracteristica. X) X= ['a'.X > 3. enrojo( Y. una lista de enteros. char. X):. 'd'. 'x'] 6) Sacar las vocales de una cadena.'b'. char*) 7) Dado el siguiente programa en PROLOG: campeonato =symbol equipo =symbol ubic =integer ubicaciones =equipo* domains predicates 43 . 'd'. caracteristica) enrojo (caracteristica. integer) Variantes:  Sumar las posiciones impares (¿cuál sería la variable anónima?). 'x' . string) que dice en el 2° string qué queda de la primera sin la letra char. 'e'.X<=5. cantidad) clauses poseecaracteristica (X .Que la tercer cadena obtenga el char intercalado en toda la extension agregar(['a' .'b'. 5) predicates sinletras ( char* . pred2(X.Lu). pred1(X.ubic) pred6(campeonato.U1).equi2.equipo) pred5(campeonato.1).[Zs|Y]) :.Lu.Zs).[X]).U) :. pred5(C. equi3.camp2. pred2(E.pred1(X. U1 < U2.[Y|Ys].Ys.[Y|Zs]) :. [_|Lu]) :.ubicaciones. pred3(E.Ys.[E|_].1) pred5(equi1.equipo. pred2(E. equi2.equi3]).: Rta. Para cada uno de los siguientes goal.elem2.pred1(C.E1.pred5(C.equi2.[].Lu).[equi1.equi1) pred6(camp3.[Ys|Y].E) :.Lu).equi1. equi4]).E1. pred4(C.ubic) pred3(equipo.equi5) pred6(camp5. equi2 E False J B No solution G camp2 8) Dado el siguiente programa: domains elem1 = symbol elem2 = elem1* elem3 = integer predicates pred1(elem1. equi4]). pred4(camp1.elem3.pred1(C.equi4.Zs).equi2.elem2) pred3(elem2.: Rta.[equi2.elem3) clauses pred1(X.ubicaciones) pred4(campeonato. pred1(camp3.E.equi3.: C error (¿por qué?) H equi1 D True I.[equi5. pred1(camp2. 44 .equi3) pred4(camp2.[].1) pred5(camp3.E2. pred5(C.pred2(E.: Rta.equi4) pred4(camp1.Lu).Lu. pred6(C.U2).pred2(X. pred2(E.: Rta.equi3.[X]).equipo.5) pred6(camp1.E2) :. pred3(E.: Rta. pred3(E. elegir cual de las respuestas factibles corresponde.equi1.5) Respuestas factibles A Otra solución F camp1 equi3 Rta.equi2) pred5(camp2. U=U1+1. [E|_]).Apunte de Paradigma Lógico Paradigmas de Programación pred1(campeonato.: Rta.U1). equi3.equipo) clauses pred1(camp1.ubicaciones) pred2(equipo. pred2(X.elem2) pred2(elem1.: Rta.elem2.pred3(E.[_|Lu].: Rta.U):.U).elem3) pred4(elem2. que permita eliminar un elemento de una lista de enteros. Escribir un programa en Prolog por el que se ingrese un string. indicar cual o cuales o ninguno de los predicados.Apunte de Paradigma Lógico pred3(X. 9) 10) Programar en Prolog : Se tiene las listas de alumnos de los distintos cursos. que devuelva el primer string y el resto de la lista.2. 13) Escribir un programa en Prolog.Y.Y). vanesa ] Se pide diseñar un programa que pueda responder a las siguientes consultas: a) Si un alumno Juan esta en el curso 2101. :. [ juan. obteniendo una nueva lista.4.Y.5 ] Agregar a las siguientes declaraciones los predicados y reglas necesarias para determinar si: 14)     Una persona es madre de más de 40 años Decir si una persona fue madre a más de 35 años Decir si una persona fue madre a mas de 35 años de un varón madrea35v(nombre) domains nombre=string sexo=char edad=integer predicates persona(nombre.C).Y <> "1".0).D). b) Dada una lista de strings. [ 3. Paradigmas de Programación :. 11) 12) Hacer un programa que dada una lista de números devuelva el mayor. edad ) 45 . sexo. natalia. resuelve el problema.X. y la cabeza de la lista. y devuelva la cantidad de letras ‘A’ y la cantidad de letras ‘Z’.X.C) :. oscar.X. pred4(Cola. pred4(["1"|Cola].pred4(X. b) En cuales cursos esta Juan. d) Agregar un string al final de una lista de strings. Además decir cómo serán las consultas. Para cada una de las siguientes preguntas. pred4(Cola. c) Dada una lista de strings que devuelva el ultimo string de la lista.C) pred4([Y|Cola]. Ejemplo: quitar ( 2. (hechos del siguiente tipo: lista(2102. a) Agregar un string al principio de una lista de strings.X.Y) pred4([].5]. c) En cuales cursos Juan y Pedro son compañeros. Escribir un programa en Prolog que permita contar los unos y ceros de una cadena de números.4. X) ==> X = [ 3.D = C + 1. edgardo. Ejemplificar. dada la venta de un artículo. list) clauses member (X. cantidad) stock_minimo (articulo.”ema”] Para simular compras de una ferretería.Y. ¿Cuál es la respuesta correcta? Indique con una circunferencia.”clara”. xx([]. list.Y).Apunte de Paradigma Lógico padrede(nombre.. !.”clara”. indique: 1) si la cantidad en stock queda mayor al stock mínimo. persona(juana. 'f'. 1) Obtiene la concatenación de dos listas 2) Obtiene los elementos que están en la segunda lista y no están en la primera 3) Obtiene los elementos que están en la primera lista y no están en la segunda 4) Obtiene los elementos que están en ambas listas 5) Ninguna de las anteriores Escribir un programa en Prolog que devuelva si un número es divisible por 5. Realizar un programa Prolog que. [X|_]). 50). ………………………………. cantidad) venta (articulo. nombre) ………………………………. xx([H|T].member(X. Y. cantidad.xx(T. T2). 15) Paradigmas de Programación domains list = integer* predicates member(integer.”maria”. member (X.X) devolverá X = [“luisa”.”rosa”. cantidad) punto_pedido (articulo. []). cantidad2) 46 . avisar por pantalla "La venta se efectua sin necesidad de compra" e indicar el stock actualizado del artículo. stock mínimo y punto de pedido (cantidad a pedir). 2) en caso contrario indicar el punto de pedido o cantidad a comprar para el artículo. 'm'. list) xx (list.[H|T2]):. xx(T. 63).Y).”maria”. Z):.member(H. 49). xx([_|T]. clauses persona(pedro. [_|Y]):.Y. _.Z). Ej. se cargan en una base de conocimientos los artículos con su respectivo stock actual. persona(alfredo. 18) domains articulo = symbol cantidad. cantidad2 = integer predicates stock_actual (articulo. 'm'. y luego mostrar un mensaje en la pantalla que diga "Es necesario comprar la cantidad arriba aconsejada". quitar(“rosa”. (True | False 16) 17) Escribir un programa en Prolog que quite un nombre de una lista de nombres.”ema”].. Y.[“luisa”. pacino. película) actor_con_kevin_bacon(actor) clauses actuaron(dibu. película = symbol predicates actuaron(actor.Apunte de Paradigma Lógico Paradigmas de Programación Ejemplo: venta (grampas. etc. 50. actor. actuaron(deniro.. 1. 19) domains actor. actuaron(pacino. actuaron(deniro. actuaron(krauss.. Si ingresaran el siguiente goal: actor_con_kevin_bacon(dibu) el resultado sería: "Dibu" "El profesor punk" "Carlitos Way" "Fuego contra fuego" "Los hijos de la calle" (muestra los nombres de las películas que se relacionan) True Otra ejecución goal: actor_con_kevin_bacon(williams) False RESTRICCION: No pueden utilizar . olmedo. tenuta. "Rambito y Rambon"). actor. "Despertares"). actuaron(zorrilla. película) relacionado (actor.. incluyendo todos los datos en la base de conocimiento 20) el resultado sería Resolver “A juan le gustan todas las gaseosas menos las bebidas cola” 47 . krauss. kevin_bacon. deniro. "Fuego contra fuego"). williams. "Los hijos de la calle").. porcel. and . "El profesor punk"). "Esperando la carroza"). Deben agregar las reglas relacionado y actor_con_kevin_bacon. "Dibu").. actuaron(porcel. X) X=6 La venta se efectua sin necesidad de compra Restricción: la cláusula venta debe ser una regla. actuaron(porcel... "Carlitos Way"). and . X) X=100 Es necesario comprar la cantidad arriba aconsejada venta (taladro. Consiste en relacionar al actor Kevin Bacon con cualquier otro actor a través de las películas que hayan protagonizado entre si. Z) devolverá: X=salmon. y así hasta las ocho soluciones posibles Si se ingresa régimen(atun. bebida(seven). carne(lomo). calorías(fruta.Y=flan.Y. calorías(pollo.150). calorías(salmon. postre(fruta). FUNDAMENTAR LAS RESPUESTAS. carne(pollo). 21) Utilizando la siguiente base de conocimientos.Z) devolverá: Y=fruta..integer) régimen(symbol. pescado(atún).Y. bebida_cola(cola). NO HECHOS domains predicates pescado(symbol) carne(symbol) principal(symbol) postre(symbol) comida(symbol.Z=180 X=salmon. bebida(eigth).symbol.. Aquí agregar las tres reglas faltantes. calorías(cerdo. calorías(lomo. resolver cual es el total de calorías que se consumen.Z=160 2 solutions principal. carne(cerdo). domains predicates gusta_juan(symbol) bebida_cola(symbol) bebida(symbol) clauses bebida(tonica)..Y=fruta. bebida(limón). comida y régimen deben ser reglas.30).Apunte de Paradigma Lógico Paradigmas de Programación Utilizar las declaraciones adjuntas y lo que falta deben ser una o más reglas. bebida(cola). 48 .. Ejemplo: Si se ingresa régimen(X.integer) clauses pescado(salmón).100). calorías(flan.120).110).. calorías(atun.Z=190 .Z=150 Y=flan. postre(flan). DEBEN PROPONER DOS SOLUCIONES ALTERNATIVAS..symbol) calorías(symbol.30).40). integer. Por . symbol) nocorrelativa(symbol) 49 . M = M2 * 10 + (N mod Z).nl.M2).ejemplo: correlativa (paradigmas . que indica si UnaMat es correlativa de OtraMat o bien tiene alguna correlativa que necesita de OtraMat. tiene la relación "correlativa (UnaMat. quehace(N. tiene_licencia(Nombre1). ¿cuál será el resultado? 24) El sistema de inscripción a la facultad tiene un base de conocimientos en el que almacena la información sobre estudiantes y materias.M). conoce_conductor_seguro(Nombre1).N. OtraMat)". sintaxis).L < N. vive_cerca_para_ir_andando(Nombre1).M) :.!.Apunte de Paradigma Lógico Paradigmas de Programación 22) Dadas las siguientes declaraciones: domains persona = symbol predicates puede_volver_casa(persona) conductor_seguro(persona) coche_propio(persona) conoce_conductor_seguro(persona) vive_cerca_para_ir_andando(persona) no_bebio(persona) tiene_licencia(persona) amigos(persona. quehace(L.M=1. symbol) correlativa(symbol. !. real) clauses quehace(L. conductor_seguro(Nombre1):no_bebio(Nombre1). Si se ingresa quehace(20. Definir entonces la regla "necesita (UnaMat. OtraMat) " que indica que UnaMat es correlativa de OtraMat.persona) clauses puede_volver_casa(Nombre1):conductor_seguro(Nombre1). write("si L < N ignore el resultado").8. coche_propio(Nombre1).L = N div Z.Z. La base de conocimientos es como la siguiente: predicates necesita(symbol.Z. Agregar la regla y hechos faltantes para que el programa al goal externo: puede_volver_casa(Quien) responda Quien=elisa Quien=felipe Quien=pablo 3 solutions 23) Interpretar y explicar qué hace el siguiente programa: domains predicates quehace(integer. En particular.M) :. Algunos ejemplos: necesita (algoritmos.plata) 50 . correlativa(algoritmos. cantidad) compras(plata. correlativa (paradigmas. páginas) clauses Jorge va de compras y tiene una lista de necesidades. paradigmas) False necesita (paradigmas. titulo. paradigmas). 25) domains titulo = symbol autor = symbol paginas = integer predicates escrito_por ( autor. discreta). algoritmos).Apunte de Paradigma Lógico Paradigmas de Programación clauses nocorrelativa (discreta). Las materias no correlativas se indican como nocorrelativa (Mat). Crear la regla compras que le resuelva las cosas que puede comprar y cuanto le sobra. correlativa (sintaxis. También tiene el precio de cada cosa. correlativa (gestion. No necesitan agregar predicado alguno. discreta) True necesita (gestion. necesita (discreta. precio) necesita(articulo. Cual) No Solutions Completar el programa con las cláusulas necesarias para mostrar un conjunto de libros y la regla necesaria (libro) que muestre los libros de más de 500 páginas.plata. sintaxis). 26) domains articulo= symbol cantidad= real precio= real plata= real predicates cuesta(articulo. páginas) libro(titulo. Cual) Cual= paradigmas Cual= sintaxis Cual= algoritmos Cual= discreta 4 Solutions.articulo. cuesta(pan. Para ello se cuenta con los 28) 51 . Jorge puede comprar: 1 huevos Le quedan: 0. ordenados en fijos y variables. país) pais_ (país) clauses participa_en_olimpíadas (Nombre1):deportista_amateur (Nombre1).5). 5). 1). 0. cuesta(jabon.50 o goal: compras(2).Apunte de Paradigma Lógico clauses necesita(jabón. consiguio_sponsors (Nombre1). El resultado es: Jorge tiene 4 y puede comprar: 1 jabon. necesita(pan. Le quedan 0.20). 1. 1. Una empresa productora de pirufios debe realizar un proyecto. cuesta(jugo. necesita(carne. Paradigmas de Programación Tal que si goal: compras(4).5). deporte) deporte_amateur (deporte) no_esta_federado (persona) ciudadano (persona. vive_pais_ (Nombre1).70). cuesta(carne. para el cual debe hacer un listado de los costos.50). cuesta(huevos.!. cuesta(queso. 4). necesita(jugo.30. Construir las reglas deportista_amateur (x) y vive_pais_olimpico (X) y agregar los hechos faltantes para que Juan. 1). 3. necesita(huevos.30).4). necesita(queso. 0. 0. 3. Pepe y María participen en las olimpíadas por motivos distintos. 27) domains persona= symbol deporte= symbol pais= symbol predicates participa_en_olimpíadas(persona) deportista_amateur(persona) consiguio_sponsors (persona) vive_pais_olimpico (persona) practica_deporte (persona. 1). 15000). Se detalla primero la salida a obtener y los predicados que el programa va a utilizar.Apunte de Paradigma Lógico Paradigmas de Programación datos de cada costo y una lista de los fijos y otro de los variables. 10000). mano_de_obra]). CF):-es_costo_fijo(T. Escribir un programa por el cual se ingresan dos listas de enteros y se genera una tercera intersección de las mismas. costo(costos_indirectos. Total) clauses costos_fijos([gastos_administrativos.[9. Se debe agregar los hechos faltantes para obtener lo requerido. depreciaciones]).4]. H). Ejemplo de la salida a obtener: Goal externo: costo_proyecto costos fijos ************* gastos_administrativos ---> 20000 gastos_ventas ---> 50000 costos_indirectos ----> 15000 depreciaciones ----> 12000 total fijos 97000 costos variables ****************** materias_primas ---> 20000 mano_de_obra -----> 10000 total variables -----> 30000 total general ------> 127000 domains lista=symbol* Total=real predicates costos_fijos(lista) costos_variables(lista) costo(symbol.4. costo(gastos_ventas.4].CF). costo(materia_prima. Ej. gastos_ventas. 1 Solution. costos_indirectos.: inters([1. debe obtener los totales para costear el proyecto. costo(gastos_administrativos. costos_variables([materia_prima.3. 12000). es_costo_fijo([_|T]. 20000). costo(mano_de_obra. symbol) imprime_costos(lista.6].X)  X=[3. Total) costo_proyecto es_costo_fijo(lista.3. Como corolario. 29) 52 . 20000).8. es_costo_fijo([H|_].2. costo(depreciaciones. 50000).
Copyright © 2024 DOKUMEN.SITE Inc.