UNIVERSIDAD VERACRUZANA DEPARTA DEPARTAMENTO MENTO DE INTELIGENCIA ARTIFICIAL ARTIFICI AL
Solución al problema de los caníbales y misioneros por búsqueda en profundidad en Matlab INTELIGENCIA ARTIFICIAL II Tarea 2
PRESENTA:
LUIS LORENZO RASCON PEREZ
Fecha de entrega: 18 de de Enero del 2012 2012 Fecha de requerimiento:
11 de Enero del 2012
A b s t r a c t : El
juego de los misioneros y los caníbales es uno de los juegos y problemas clásicos. El algoritmo implementado en este trabajo permite hallar una solución en base a una búsqueda en profundidad sobre el árbol del espacio de soluciones.
Inteligencia Artificial
1
Technical Discussion: El juego consiste en pasar a través de una lancha a todos los misioneros(3) y a todos los caníbales(3) al otro lado del rio usando una lancha. Las reglas del juego son las siguientes: -La lancha solo puede llevar 2 personas -La lancha no puede pasar al otro lado sola -No debe haber más caníbales de que misioneros en ninguno de los 2 lados porque sino se comerán al misionero que este en desventaja. El algoritmo se diseñó en base a un árbol que representa el estado de soluciones, donde cada nodo es un estado de solución valido de 5 posibles estados (nodos hijo). Para hacer el recorrido del árbol se crea una pila (una matriz) que irá acumulando los vectores (nodos) hijo del nodo actual (el cual al inicio del programa será el estado inicial con 3 caníbales y 3 misioneros en el lado izquierdo o derecho). En el algoritmo para evitar el ciclo interminable debe restringirse a no repetir una vez tras otra el mismo movimiento, así usando una variable que calcula el último movimiento realizado para el nodo actual.
Inteligencia Artificial
2
Discussion of results: El diseño y desarrollo de este algoritmo en Matlab me ha permitido ver que es bastante intuitiva y rápida la forma de desarrollar pequeños prototipos con ayuda del REPL y ver sus resultados con la capacidad de graficarlos. Una cosa en la que hay que poner mucha atención para hacer un programa que sepa jugar con los misioneros y caníbales es la correlación de las variables de los caníbales y misioneros en ambos lados y cómo aunque no está escrito en las reglas nosotros razonamos de manera intuitiva que si en un estado hay más caníbales que misioneros, siempre y cuando los últimos sean 0, este es un estado valido. En este algoritmo decidí expandir todos los hijos del nodo actual (el que fuere en su momento) para después meterlos en orden a la pila y ya seguir con el funcionamiento normal de la pila (First in, Lasto out). Esto debido a que la proyección que quería dar del recorrido sobre el árbol fuera a profundidad de izquierda a derecha ( Imagen 1 y 2 ). El recorrido sobre el árbol se acumuló en cada nodo como una propiedad más de este quedando en el extremo izquierdo el movimiento realizado anteriormente y hacia la derecha los padres hasta llegar al extremo derecho con el nodo inicial ( Imagen 3). También se muestra al final la solución en pasos descriptivos en español ( Imagen 3).
Imagen 1
Inteligencia Artificial
3
Imagen 2
Imagen 3
Inteligencia Artificial
4
Appendix A continuación se despliega el código fuente del programa en Matlab: display 'Problema de los misioneros y los canibales. El estado inicial E0 indica 3 canibales y 3 misioneros del lado izquierdo' %La pila se inicializa con el estado inicial E0 % [Ci,Mi,Cd,Md,lado,rutaSolucion] E0=[3,3,0,0,0,0] Esol=[0,0,3,3,1] Pila=E0 solucion=0; while(solucion==0) %Codigo dentro del bucle %Generador de posibles Movimientos (Nodos hijo a partir de E0) can_izq=E0(1,1); mis_izq=E0(1,2); can_der=E0(1,3); mis_der=E0(1,4); lado_act=E0(1,5); digitos=str2double(regexp(int2str(E0(:,6)),'\d','match')); padre=E0(1,6); LastMove=digitos(1,1); if(E0(1:5) == Esol) solucion=1; display 'Una solución al problema de los misioneros y los canibales es la siguiente:' digitos for i=length(digitos):-1:1 switch(digitos(:,i)) case 0 display '0.-Estado Inicial.' case 1 display '1.-Mover 1 canibal y 1 misionero.' case 2 display '2.-Mover 2 misioneros.' case 3 display '3.-Mover 2 canibales.' case 4 display '4.-Mover 1 canibal.' case 5 display '5.-Mover 1 misionero.' end end
else %1.-si el estado solución aun no ha sido alcanzado entonces se expande el %nodo llenando la pila con los nodos hijos que son estados validos. %Siempre existen 5 posibles estados hijos para un nodo, pero no todos son %estados de solución validos. %2.-Ya que los valores del nodo actual han sido calculados antes de este %paso, lo sacamos de la pila y establecemos la variable solucion a 0.
Inteligencia Artificial
5
%3.-Se llena la pila con los hijos del estado actual(solo estados validos) %4.-Se toma el nodo en el top de la pila y se procesa de la misma manera solucion=0; Pila=Pila(2:length(Pila(:,1)),:) %pasando 0 canibales y 1 misioneros if(LastMove~=5 && (((lado_act==0 && mis_izq-1>=0)&&((can_izq<=mis_izq1||mis_izq-1==0) && (can_der<=mis_der+1||mis_der+1==0)))||((lado_act==1 && mis_der1>=0)&&((can_izq<=mis_izq+1||mis_izq+1==0) && (can_der<=mis_der-1||mis_der1==0))))) hijo=5; ruta_sol=str2double([int2str(hijo),int2str(padre)]); if(lado_act==0) E1= [can_izq, mis_izq-1 , can_der, mis_der+1,1,ruta_sol] else E1= [can_izq, mis_izq+1 , can_der, mis_der-1,0,ruta_sol] end Pila=[E1;Pila] end %pasando 1 canibal y 0 misioneros if(LastMove~=4 &&(((lado_act==0 && can_izq-1>=0)&&((can_izq1<=mis_izq||mis_izq==0) && (can_der+1<=mis_der||mis_der==0)))||((lado_act==1 && can_der-1>=0)&&((can_izq+1<=mis_izq||mis_izq==0) && (can_der1<=mis_der||mis_der==0))))) hijo=4; ruta_sol=str2double([int2str(hijo),int2str(padre)]); if(lado_act==0) E1= [can_izq-1, mis_izq , can_der+1, mis_der,1,ruta_sol] else E1= [can_izq+1, mis_izq , can_der-1, mis_der,0,ruta_sol] end Pila=[E1;Pila] end %pasando 2 canibales en la lancha if(LastMove~=3 &&(((lado_act==0 && can_izq-2>=0)&& ((can_izq2<=mis_izq||mis_izq==0) && (can_der+2<=mis_der||mis_der==0)))||((lado_act==1 && can_der-2>=0)&& ((can_izq+2<=mis_izq||mis_izq==0) && (can_der2<=mis_der||mis_der==0))))) hijo=3; ruta_sol=str2double([int2str(hijo),int2str(padre)]); if(lado_act==0) E1= [can_izq-2, mis_izq , can_der+2, mis_der,1,ruta_sol] else E1= [can_izq+2, mis_izq , can_der-2, mis_der,0,ruta_sol] end Pila=[E1;Pila] end %pasando 2 misioneros en la lancha if(LastMove~=2 &&(((lado_act==0 && mis_izq-2>=0)&& ((can_izq<=mis_izq2||mis_izq-2==0) && (can_der<=mis_der+2||mis_der+2==0)))||((lado_act==1 && mis_der2>=0)&& ((can_izq<=mis_izq+2||mis_izq+2==0) && (can_der<=mis_der-2||mis_der2==0)))))
Inteligencia Artificial
6
hijo=2; ruta_sol=str2double([int2str(hijo),int2str(padre)]); if(lado_act==0) E1= [can_izq, mis_izq-2 , can_der, mis_der+2,1,ruta_sol] else E1= [can_izq, mis_izq+2 , can_der, mis_der-2,0,ruta_sol] end Pila=[E1;Pila] end %pasando 1 canibal y 1 misionero en la lancha if(LastMove~=1 &&(((lado_act==0 && can_izq-1>=0 && mis_izq-1>=0)&& ((can_izq1<=mis_izq-1||mis_izq-1==0) && (can_der+1<=mis_der+1||mis_der+1==0)))||((lado_act==1 && can_der-1>=0 && mis_der1>=0 && ((can_izq+1<=mis_izq+1||mis_izq+1==0) && (can_der-1<=mis_der-1||mis_der1==0)))))) hijo=1; ruta_sol=str2double([int2str(hijo),int2str(padre)]); if(lado_act==0) E1= [can_izq-1, mis_izq-1 , can_der+1, mis_der+1,1,ruta_sol] else E1= [can_izq+1, mis_izq+1 , can_der-1, mis_der-1,0,ruta_sol] end Pila=[E1;Pila] end E0=Pila(1,:) solucion; end end
Inteligencia Artificial
7