Ejemplos prolog

  • Published on
    11-Dec-2014

  • View
    127

  • Download
    2

Embed Size (px)

Transcript

<p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS CURSO DE SISTEMAS BASADOS EN EL CONOCIMIENTO 1 PROFESOR: PERVYS RENGIFO RENGIFO AUTOR: FELIPE FORERO INGENIERIA DE SISTEMAS VIII SEMESTRE 2007-I</p> <p>1) Elabore un programa en prolog que permita resolver el problema de las Torres de Hanoi. Solucin: Las torres de Hanoi se ha convertido en uno de los problemas clsicos dentro de las ciencias de la computacin- El problema es fcil de comprender, y admite una solucin recursiva simple. La historia puede ser embellecida de varias formas. Hay tres varillas, una de las cuales tiene un nmero de discos insertados, formando una pirmide. La cuestin fundamental es los discos estn insertados en orden de tamao, con el ms grande en el fondo. La figura siguiente ilustra la condicin inicial del problema Varilla de la izquierda Varilla central Varilla de la derecha</p> <p>Figura 1: Ilustracin de la condicin inicial del problema de la torre de Hanoi (Tomada de http://www.pbclibrary.org/raton/towers.htm) La tarea es transferir los discos desde la varilla de la izquierda hasta la varilla de la derecha, apoyndose, si se necesita, en la varilla central. Lo que hace no trivial este problema es que se deben cumplir tres restricciones: 1) Los discos pueden ser movidos uno a la vez. Si no estuviera esta restriccin el problema se resolvera moviendo el bloque de la varilla actual a la varilla de la derecha. 2) Un disco slo puede ser movido a otra varilla. Otra vez, esto previene una solucin trivial dejar los disco en el piso, y luego insertarlos en las varilla de la derecha. Esta restriccin obliga a utilizar la varilla del centro para almacenar temporalmente los discos. 3) Un disco ms grande nunca puede ser coloca encima de uno ms pequeo.</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS Si esta restriccin no existiera, el problema podra, otra vez ser fcilmente resuelto. Simplemente se pasaran todos discos en la varilla central y luego trasladaran a la varilla de la derecha. El problema computacional bsico de las torres de Hanoi consiste en escribir un programa que incluya las operaciones necesarias para realizar la transferencia de un conjunto de N discos desde la varilla de la izquierda hasta la varilla de la derecha. La manera de pensar un problema recursivo es siempre concentrarse en dos preguntas: a) Cul es el caso base El caso ms simple de las torres de Hanoi podra ser para una pirmide de solo un disco. El caso ms simple es a menudo directo el es fcil de olvidar pero es fundamental para el xito de cualquier recursin. Aqu, la cuestin es esencialmente esta: Como transferir una pila de un disco desde el la varilla de la izquierda, utilizando la varilla de la mitad( si es necesario), a la verilla de la derecha?. La respuesta es directa: Slo mueva el disco de la pila de la izquierda a la pila de la derecha. Tambin podra tomarse como caso base, el caso de que no haya discos. En este caso la respuesta es muy simple: Si no hay discos, entonces, no haga nada. En este momento no se sabe precisamente como formalizar esta respuesta. Debido a que el caso base es el ms simple, su definicin podra no aclarar qu factores se deben tomar en cuenta para la solucin general del problema, es decir que argumentos tendra la funcin o el predicado principal que aproxime la solucin. Sin embargo, el planteamiento si hace una distincin entre dos operaciones y el tipo de entidades a las que se aplican: Transferencia de pilas(de discos) y movimiento de un disco individual. Recuerde que la tarea general es transferir una pirmide de n discos, desde una varilla a otra, apoyndose en una tercera varilla como almacenamiento temporal, pero una de las restricciones establece que su solucin debe involucrar el movimiento de discos individuales de una varilla a otra. b) Cual es el caso recursivo Pensar acerca de este problema recursivamente es pensar cmo puede usar la transferencia de una pila de discos para ayudar en su propia definicin, es decir pensar cmo el problema de la transferencia de N discos puede ser reducido a un caso ms simple de transferencia. Una aproximacin inicial para este problema se logra haciendo la siguiente reflexin: Se deben pasar todos los discos desde la varilla de la izquierda hasta la varilla de la derecha pero no puede colocarse un disco ms grande sobre uno ms pequeo, moviendo solo un disco a la vez. Si pudiera pasar el disco ms grande desde la varilla de la izquierda a la varilla de la derecha, tendra un comienzo excelente para transferir la pila de discos hasta la varilla de la derecha, ya que para que esta transferencia sea exitosa los discos se deben transferir aqu desde el mayor hasta el menor (recuerde que as estn ordenados en la pila de la izquierda). Sin embargo, para hacer esto se requieren dos condiciones:</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS Que el disco ms grande quede solo en la varilla de la izquierda(sin ningn disco encima de l) y que la varilla de la derecha no tenga, en este momento, ningn disco. De estas condiciones resulta como consecuencia que los N-1 discos que se encuentran inicialmente encima del disco ms grande deben ser transferidos a la varilla central(utilizando, si se requiere, a la varilla de la derecha como varilla de almacenamiento temporal). La siguiente grfica ilustra estas condiciones:</p> <p>Figura 2: Se deben pasar n-1 discos desde la varilla izquierda hasta la varilla central</p> <p>Figura 3: Luego se puede pasar el disco ms grande desde la varilla izquierda hasta la varilla de la derecha.</p> <p>Figura4: Estado final luego de las acciones anteriores.</p> <p>Esto sugiere la primera fase de la recursin: Con el fin de transferir N discos desde la varilla de la izquierda a la varilla de la derecha, se debe transferir N1 discos desde la varilla de la izquierda a la varilla central. El problema de transferir una pila de N discos se ha reducido al problema de transferir una pila de N-1 discos. Observe que durante la transferencia de los N-1 discos de la varilla de la izquierda hasta la varilla del centro, la varilla de la derecha actuar como varilla de almacenamiento temporal. Sin embargo, a pesar de que en el proceso de este paso, la varilla de la derecha almacenar temporalmente discos, al final de este paso, la varilla de la derecha no contendr ningn disco, ya que todos estarn en la varilla del centro(N-1 disco) y en la varilla de la izquierda (el disco ms grande)(ver figura 3). El paso siguiente de la recursin es el paso pivotal: mover el disco ms grande desde la varilla de la izquierda hasta la varilla de la derecha(ver Figuras 3 y 4). La tercera fase de la recursin requiere que se transfiera los N-1 discos desde la varilla central hasta la varilla de la derecha, durante lo cual, la varilla de la izquierda actuar como varilla de almacenamiento temporal. Esta solucin requiere que se distinga entre cada varilla particular y el papel que juega en cualquier fase de la operacin. Cuando se inicia con N discos, la varilla de la izquierda es la fuente y la varilla de la derecha es el destino y la varilla central es la de almacenamiento temporal. Cuando esto se reduce al problema de transferir N-1 discos, la varilla de la mitad es la fuente, la de la derecha es el destino y la de la izquierda es la de almacenamiento temporal. Implementacin en Prolog Para la implementacin se requiere un predicado que permita transferir una pila de N discos desde una fuente X, apoyndose como almacenamiento temporal en Y, a un destino Z, que se podra declarar como: transfiera(N,X,Y,Z).</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS Caso Base: El caso base del algoritmo recursivo, como se mencion ms arriba podra ser el caso en que la pila de la izquierda tenga solamente un disco, para lo cual se requiere solamente, mover el disco desde el origen hasta el destino. En prolog, esto podra escribirse como: transfiera(1,Izquierda,Centro,Derecha):- mueva_disco(Izquierda,Derecha). Tambin podra considerarse como caso base el caso ms trivial, en el cual no hay disco, en este caso simplemente, no hay que hacer nada. En prolog se escribira as: transfiera(0,Izquierda,Centro,Derecha). Usted puede elegir uno de estos dos casos bases. Para este ejemplo se elegir el caso de 0 discos como el caso base, y se exigir que N&gt;=0.</p> <p>Caso Recursivo Aqu simplemente se debe expresar en la sintaxis de prolog el algoritmo discutido anteriormente: Para transferir N discos desde la varilla Izquierda hasta la varilla Derecha haga lo siguiente: Transfiera N-1 discos desde la varilla de la izquierda hasta la varilla central, utilizando la varilla de la derecha como varilla de almacenamiento temporal. Luego, mueva el disco ms grande (que qued solo en la varilla de la izquierda), desde la varilla Izquierda hasta la varilla Derecha. A continuacin, transfiera los N-1 discos desde la varilla Centro, hasta la varilla Derecha, utilizando la varilla izquierda como varilla de almacenamiento temporal. En prolog, esto se expresara de la siguiente forma transfiera(N,Izquierda,Centro,Derecha):como apoyo %Para transferir N discos de Izquierda a Derecha, utilizando Centro</p> <p>N&gt;0,M is N-1, % se asegura que N&gt;0 y almacena N-1 en M transfiera(M,Izquierda,Derecha,Centro), %transfiera N-1 discos de Izquierda a Centro, utilizando Derecha comoapoyo</p> <p>mueva_disco(Izquierda, Derecha), %mueva el disco mayor de Izquierda a Derecha transfiera(M,Centro,Izquierda,Derecha). %transfiera N-1 discos de Centro a Derecha, utilizando a Derecha comoapoyo</p> <p>Ahora se define el predicado mueva_disco(Izquierda, Derecha). Este predicado solo debe indicar de donde a donde se realizar el movimiento del disco mueva_disco(Izquierda,Derecha):- write('Mueva el disco de arriba desde '), write(Izquierda), write(' hasta '), write(Derecha),nl. Finalmente el programa quedara de la siguiente manera: transfiera(0,Izquierda,Centro,Derecha). transfiera(N,Izquierda,Centro,Derecha):- N&gt;0,M is N-1,</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS transfiera(M,Izquierda,Derecha,Centro), mueva_disco(Izquierda, Derecha), transfiera(M,Centro,Izquierda,Derecha). mueva_disco(Izquierda,Derecha):- write('Mueva el disco de arriba desde '), write(Izquierda), write(' hasta '), write(Derecha),nl. mueva_disco(Izquierda,Derecha):- write('Mueva el disco de arriba desde '), write(Izquierda), write(' hasta '), write(Derecha),nl. Al compilar este programa y correrlo con 3 discos en la varilla izquierda, mediante transfiera(3,izquierda,centro,derecho), se obtiene:</p> <p>2) Un sistema de produccin consiste en un conjunto de pares situacinaccin, indicando que si esta situacin surge, tome esta accin. Un ejemplo de un sistema de produccin es el programa numerales romanos dado abajo:</p> <p>% Numerales Romanos para 1 = 10, X =&lt; 39, write('X'), Y is X - 10, romano(Y). romano(X) :X == 9, write('IX'). romano(X) :X &gt;= 5, X =&lt; 8, write('V'),</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMASY is X - 5, romano(Y). romano(X) :X == 4, write('IV'). romano(X) :X &gt;= 1, X =&lt; 3, write('I'), Y is X - 1, romano(Y). romano(0) :- nl.</p> <p>Estudie como trabaja este algoritmo, y extindalo para manejar todos los nmeros desde 1 a 399. Muestre que su programa funciona para 49, 51, 99, 101,299, y 399. Escriba un ciclo que despliegue los nmeros romanos de todos los nmeros entre 1 y 399 inclusive. SOLUCION: Se puede notar que la manera de procesar el nmero es de los mayores valores hacia los menores, ya que es la manera de escribir un nmero romano, encontramos primero los smbolos de mayor peso, o que representan mayor valor. Para expender el cdigo para que maneje los nmero del 1 al 399, empezamos de manera similar, procesando primero los nmeros de mayor valor, descomponindolo hasta llegar a un mnimo valor. Antes de comenzar se valida que el nmero este en el rango que el algoritmo puede manejar:</p> <p>romano(X) :X &gt; 399, write('Numero debe estar entre 1 y 399'), nl. romano(X) :X &lt; 0, write(' Numero debe estar entre 1 y 399'), nl. Empezamos entonces con los nmeros que sean mayores o iguales que 100 y menores a 400, si esto sucede, se imprime una C como parte del resultado, y le restamos al numero de entrada estos 100 que ya se representaron, y volvemos a llamar la funcin, de manera recursiva, de tal manera que vuelva a hacer esta evaluacin, y as poner tantas C como sea necesario o seguir con uno de los predicados siguientes: romano(X) :X &gt;= 100, X =&lt; 399, write('C'), Y is X - 100, romano(Y).</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS Una vez el numero sea menor que 100, se evala de nuevo, y si esta entre 90 y 99, agregamos a la salida XC, que es la manera de representar al 90, al hacer esto, tenemos que restarle al numero 90, ya que ya fueron representados, y se vuelve a llamar la funcin con este nuevo numero como argumento romano(X) :X &gt;= 90, X &lt; 100, write('XC'), Y is X-90, romano(Y). Si el nmero esta entre 50 y 89, se le agrega a la salida una L, que representa el numero 50 en romano, y estos 50 son restados del numero a representar, y se vuelve a llamar la funcin romano con este nuevo valor romano(X) :X &gt;= 50, X &lt; 90, write('L'), Y is X - 50, romano(Y). En el caso en que el nmero al que se le aplica la funcin romano es mayor o igual a 40 y menor que 50, se agrega a la salida XL, que representa 40 en romano. Como se ha venido haciendo, se le resta al numero procesado 40, que ya fueron representados, y con este valor se llama de nuevo la funcin romano, para seguir procesando el valor restante. Hasta este punto es la modificacin que se le tuvo que hace al algoritmo para que procesara nmeros del 1 a 399. romano(X) :X &gt;= 40, X &lt; 50, Y is X-40, write('XL'), romano(Y). En otro caso, si el numero a procesar es mayor o igual a 10 y menor que 40, se agrega a la salida una X que representa un 10, estos se le restan a el numero y se vuelve a llamar la funcin con este nuevo valor romano(X) :X &gt;= 10, X =&lt; 39, write('X'), Y is X - 10, romano(Y). Cuando el nmero es igual a 9, se agrega a la salida IX, que representa al nmero 9 en romano, y no se vuelve a llamar la funcin. Cuando el nmero esta entre 5 y 8, se agrega a la salida V, se le resta 5 al nmero y se vuelve a llamar la funcin con este nuevo valor.</p> <p>FUNDACIN UNIVERSITARIA KONRAD LORENZ-PROGRAMA DE INGENIERA DE SISTEMAS romano(X) :X == 9, write('IX'). romano(X) :X &gt;= 5, X =&lt; 8, write('V'), Y is X - 5, romano(Y). En otra entrada a la funcin, si el nmero es igual a 4, se agrega a la salida IV, y no se vuelve a llamar la funcin, ya que el nmero estara totalmente representado en romano. Cuando el numero es menor que 4 y mayor o igual a 1, se agrega a la salida I, se resta 1, y se vuelve a llamar la funcin con el nuevo valor. El algoritmo quedara de la siguiente manera:</p> <p>% Numerales Romanos para 1 = 100, X =&lt; 399, write('C'), Y is X - 100, romano(Y). romano(X) :X &gt;= 90, X &lt; 100, write('XC'), Y is X-90, romano(Y). romano(X) :X &gt;= 50, X &lt; 90, write('L'), Y is X - 50, romano(Y). romano(X) :X &gt;...</p>

Recommended

View more >