Está en la página 1de 22

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Ingeniera en Sistemas UNICEN

Anlisis y Diseo de Algoritmos II 2011 Trabajo Prctico Especial

Flood Filler

Comisin: Martes Ayudante: Antonela Tommasel Nro de grupo: 18 Integrantes: Amalia L. Thomas Andrs Espinosa e-mails: amaliathomas@hotmail.com andresespinosa@hotmail.com
-1-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

NDICE

Seccin Introduccin Fundamentos Tericos Herramientas provistas para el desarrollo y anlisis de los algoritmos Interfaz de programacin de la aplicacin DFS BFS A Estrella Heurstica A*1 Heurstica A*2 Heurstica A*3 Funciones Auxiliares Interpretacin de los resultados Conclusiones Referencias

Pgina

3 3 4

5 6 8 10 11 13 16 18 20 22 22

-2-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Introduccin
El juego Flood Filler es un problema combinatorio donde el jugador debe pensar una solucin consistente de una combinacin de colores (o movimientos) de forma tal que realizando operaciones eficientemente llegue a inundar el tablero. El juego est compuesto de una serie de tableros compuestos por casilleros de distintos colores. El objetivo es conseguir que todos los casilleros contengan el mismo color, mediante una seleccin secuencial de los colores disponibles. Se considera un movimiento a la seleccin de uno los colores posibles, que siempre se coloca en el casillero superior izquierdo (casillero de inicio), el cual inicialmente se encuentra sin color. A partir de la seleccin de un nuevo color, los casilleros contiguos en forma horizontal o vertical al casillero de inicio, que tengan el mismo color, sern configurados con el nuevo color, y esta forma de reemplazo de colores, se repetir para cada uno de los casilleros contiguos que hayan modificado su color. El juego se termina cuando todos los casilleros visualizan el mismo color. La versin del juego que utilizaremos tiene las siguientes caractersticas y restricciones: El tamao del tablero es de 10 casilleros de ancho por 10 casilleros de alto. Los movimientos permitidos se basan en la eleccin de uno de 4 colores posibles (azul, verde, rojo o violeta) No existe un lmite en la cantidad de movimientos a realizar en cada uno de los tableros. El objetivo del trabajo es implementar diversos algoritmos de bsqueda que permitan resolver los tableros propuestos por el juego Flood Filler.

Fundamentos tericos
El objetivo del trabajo es desarrollar algoritmos que obtengan, lo ms eficientemente posible, la sucesin de movimientos que se deben realizar para conseguir un tablero con todos los casilleros del mismo color. Los algoritmos implementados son denominados algoritmos de bsqueda y a continuacin describiremos los fundamentos tericos para entender por qu los mismos resultan adecuados para resolver este problema en particular. Para resolver el problema se utiliz el concepto de grafo para modelar la dinmica del juego. De esta forma cada configuracin o estado del tablero se considerar un vrtice. Luego, las selecciones de los colores disponibles, en un estado particular, constituirn los arcos hacia nuevos estados. La configuracin de los nuevos estados ser la obtenida a partir de procesar la seleccin de un nuevo color y el consecuente reemplazo de colores en los casilleros que corresponda. Una vez realizado este reemplazo, se podr elegir un nuevo color. El siguiente diagrama de ejemplo muestra el grafo de bsqueda, donde las configuraciones del tablero luego de los movimientos posibles constituyen los nodos y las selecciones que se realizan son los arcos. Ntese que en ste modelo un movimiento puede llevar a un estado repetido, o no cambiar el color de ningn casillero.

-3-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Herramientas provistas para el desarrollo y anlisis de los algoritmos


Para la implementacin de los algoritmos se provee un proyecto, que consiste en la implementacin completa del juego Flood Filler. El mismo incluye la lgica del juego (reglas, configuracin y control del tablero de juego), as como una interfaz de usuario que permite probar los distintos tableros, jugando de forma manual y tambin, a travs de las soluciones obtenidas por los distintos algoritmos que se van a implementar. El control del modo manual es mediante el click izquierdo del mouse sobre el men de seleccin de colores. Durante la reproduccin de las soluciones obtenidas por los distintos algoritmos, es necesario indicar que se muestre el prximo paso presionando la tecla espaciadora. De esta forma se puede visualizar en forma pausada los movimientos que llevaron a la solucin encontrada. Cada uno de los algoritmos de bsqueda implementados cumple la siguiente interfaz:
bool (*PlanAlgorithm)(GameSimulator & sim, unsigned int & depth, list<BoardController::Tile> & solution)

-4-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Esta interfaz presentada por PlanAlgorithm determina que se debe retornar un valor booleano que indica si se pudo alcanzar el estado objetivo o no. Adems, establece que se recibe como parmetros: un objeto sim de tipo GameSimulator, que permite simular el juego y gestionar los estados generados; un valor entero depth que nos permite limitar la profundidad de la bsqueda; y una lista solution donde se almacenarn los colores que nos permiten alcanzar el estado objetivo, si fue encontrado. En los archivos FloodFillerAlgorithms.h y FloodFillerAlgorithms.cpp, se encuentran las declaraciones y las definiciones del algoritmo de ejemplo, y el resto de los algoritmos cuya implementacin se deber completar (todos ellos de acuerdo a la interfaz general dada por PlanAlgorithm). Es posible agregar ms algoritmos en estos archivos. En el archivo main.cpp se invoca a la funcin runFloodFiller. Esta funcin recibe en un vector, punteros a las funciones que implementan los algoritmos y una cadena de caracteres necesaria para crear la opcin correspondiente en el men. La opcin para el modo manual es una funcin especial y el resto (dfs, bfs, astar1, etc) corresponden a los algoritmos de ejemplo y los stubs del resto de los algoritmos a implementar. Si se implementan algoritmos adicionales, se deber agregar la opcin correspondiente al vector.
vector<pair<PlanAlgorith, string> > algorithms; algorithms.push_back(make_pair(&manualMode, "Modo Manual")); algorithms.push_back(make_pair(&dfs, "DFS")); algorithms.push_back(make_pair(&bfs, "BFS")); algorithms.push_back(make_pair(&astar1, "A* Heuristica 1")); algorithms.push_back(make_pair(&astar2, "A* Heuristica 2")); algorithms.push_back(make_pair(&astar3, "A* Heuristica 3"));

Interfaz de programacin de la aplicacin


Para la implementacin de los algoritmos de busqueda, se dispone de los siguientes mtodos: Uno de los parmetros es del tipo GameSimulator, objeto que permite manipular los estados del juego proveyendo las facilidades necesarias para implementar los algoritmos de bsqueda para resolver el problema planteado. Este objeto simulador posee, entre otros, varios mtodos para la manipulacin de estados: El tipo GameState representa un estado de juego que puede guardarse y recuperarse ms tarde. A travs del mtodo update el simulador va avanzando de estado, guardando automticamente los estados anteriores. El mtodo undoUpdate permite volver al estado inmediatamente anterior. El mtodo getState retorna la representacin del estado del juego actual como una referencia a una instancia de GameState que puede guardarse en una estructura externa al simulador. El mtodo setState lleva el estado de la simulacin al estado que se indica como parmetro. Se distinguen dos tipos de estados que guarda el simulador. Los estados anteriores: es una lista de los estados por los que pas la simulacin, ya sea por una invocacin al mtodo update o setState; una invocacin al mtodo undoUpdate eliminar el ltimo estado alcanzado. El mtodo isInPath consulta si un estado dado se encuentra en la lista de los estados anteriores. Los estados generados: es un conjunto de todos los estados por los que pas la simulacin. Para estos estados se puede guardar -5-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

informacin; la ms importante un valor de visitado (booleano) que se activa con el mtodo addVisited y se consulta con el mtodo getVisited (de esta forma el simulador implementa directamente la lista de estados visitados o cerrados de muchos algoritmos). El juego en s est representado por el tipo Game. Una referencia al juego se puede obtener a travs del simular, mediante el mtodo getGame(). El mismo permite acceder a los elementos del juego por su tipo, en este caso, el controlador del tablero a travs del mtodo getRule(s). Este controlador est implementado mediante la clase BoardController, la cual brinda una interfaz adecuada para acceder a cada uno de los casilleros del tablero, conocer los colores disponibles, entre otras funciones. Una vez que se consigui crear la interfaz y modelar con un grafo el desarrollo del juego, se ve que es posible aplicar los algoritmos clsicos de recorrido (DFS, BFS) adaptados a la bsqueda del estado objetivo (es decir una configuracin del tablero donde todos los casilleros contengan el mismo color). Esta adaptacin lleva a lo que se conoce como algoritmos de bsqueda por fuerza bruta, ya que exploran sistemticamente los estados, generando los mismos en el orden que define cada tipo de recorrido.

DFS
Como parte del proyecto se incluye la implementacin del algoritmo de bsqueda exhaustiva por prufundidad (DFS). Una aplicacin de la bsqueda en profundidad a la resolucin del problema es representada en forma de pseudocdigo a continuacin.
DFS (EstadoJuego E, Solucin S): Si E es el estado objetivo Devolver la solucin con los pasos ejecutados hasta el momento Sino Si E no fue visitado anteriormente Marcar a E como visitado Para cada movimiento vlido, M, sobre el tablero en E Generar el nuevo estado E' ejecutando M y procesando el reemplazo de colores Agregar M a S DFS(E', S) Si se encontr solucin Terminar y devolver la solucin Sino Volver el estado actual a E, y sacar a M de S

En primera parte, se utilizan de los mtodos del simulador para la consulta del estado; a travs del mtodo isGameOver se determina si el juego finaliz. En el caso de que el juego termin, se consulta el resultado de finalizacin, con el mtodo getGameOverResult. A continuacin se utilizan los mtodos del simulador para la manipulacin de los estados de la simulacin. Como primer paso se obtiene una referencia al estado actual con el mtodo getCurrentState. Luego, se consulta si el estado actual ya fue visitado en la rama actual de bsqueda, mediante el mtodo isInPath. Para este algoritmo es la nica verificacin que se debe considerar. El manejo de estados visitados, que se mencion anteriormente, slo es necesario si queremos evitar llegar a un estado visitado anteriormente an por ramas distintas de la bsqueda. Luego se sigue con la expansin de los estados hijos. Para esto se debe seleccionar un nuevo color e indicarle al tablero que realice el reemplazo de colores correspondiente. Es as que se obtiene una referencia al tablero utilizando el mtodo -6-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

getRule de la clase Game. Dicha referencia se manipula a travs de un tipo de puntero especial dado por la clase ComponentPtr. Una vez obtenido el elemento del juego que representa al tablero, se procede a obtener los colores disponibles (getTiles) y a ubicar el color elegido (fill). Luego de ejecutar la accin se pasa al estado siguiente del juego utilizando el mtodo update del simulador. Es en este punto que se hace el llamado recursivo. Al retornar de la recursin se puede haber encontrado la solucin o no. En caso negativo se retorna al estado previo a la ejecucin de la accin a travs del mtodo undoUpdate. Durante la ejecucin de la acciones se va manteniendo la lista de colores elegidos que formarn parte de la solucin, teniendo cuidado de quitar la ltima accin al retornar a un estado previo del juego. El cdigo de la implementacin del algoritmo discutido es:
bool dfs (GameSimulator & sim, unsigned int & depth, list<BoardController::Tile> & solution) { if (sim.isGameOver()) { if (sim.getGameOverResult() == GameOverRule::WIN) { cout << "--- Se gano el juego\n\n"; return true; } else { cout << "--- Se perdio el juego\n\n"; return false; } } else if (solution.size() == depth) { cout << "--- PODA: se alcanzo la longitud maxima de la solucion\n\n"; return false; } else { const GameState * currentState = sim.getCurrentState(); if (!sim.isInPath()) { cout << "--- Se agrega el estado nuevo\n\n"; ComponentPtr<BoardController> board(sim.getGame()>getRule(BOARD)); cout << "---- Detalle de la configuracin del tablero:\n"; cout << *board; list<BoardController::Tile> tiles; board->getTiles(tiles); bool found = false; list<BoardController::Tile>::iterator tile = tiles.begin(); while (!found && (tile != tiles.end())) { cout << "--- Se ejecutara la accion: " << *tile << "\n\n"; solution.push_back(*tile); board->fill(*tile); sim.update(); cout << "--- Se actualizo el estado\n\n"; found = dfs(sim, depth, solution); if (!found) { cout << "--- Se vuelve al estado anterior\n\n"; solution.pop_back(); sim.undoUpdate(); } tile++; } return found; } else { cout << "--- El estado ya fue visitado\n\n"; return false; } } }

-7-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Las soluciones que retorna el algoritmo para los cuatro tableros tienen 25, 21, 24 y 27 pasos, cuando la solucin ptima se alcanza en 10 pasos para los primeros tres tableros y 11 para el ltimo. Adems se nota al probar la solucin que muchos de los movimientos que realiza la simulacin no avanzan hacia la finalizacin del juego, es decir, a veces elige un color que no transforma ningn casillero nuevo. Esto se debe simplemente al funcionamiento del algoritmo; que recorre el grafo en preorden hasta que llega al nmero mximo de pasos (30), y entonces prueba por la rama siguiente. De esta forma, se devolver la primera solucin que se encuentra, sea sta eficiente o no. Entonces, a pesar de que el algoritmo de bsqueda en profundidad encuentra una solucin de bajo costo computacional, es ineficiente en cuanto a nmero de pasos y eficiencia de los movimientos elegidos.

BFS
Por otro lado se implement el algoritmo de bsqueda exhaustiva a lo ancho (BFS). Una aplicacin de este algoritmo al problema se detalla a continuacin en forma de pseudocdigo. Ntese que el algoritmo fue diseado para recorrer el grafo de estados de juego en forma iterativa, a diferencia del DFS que lo recorre recursivamente.
BFS(EstadoJuego E, Solucin S): Mientras no se encuentre la solucin Si E no fue visitado anteriormente Marcar a E como visitado Para cada movimiento vlido, M, sobre el tablero en E Generar el nuevo estado E' ejecutando M y procesando el reemplazo de colores Agregar E' al final de una lista de estados auxiliar L Agregar la lista de padres de E' al final de otra lista auxiliar paralela C. Si E' es el estado objetivo Terminar y devolver la solucin con los pasos ejecutados hasta el momento, guardados en C Volver el estado actual a E Sacar el primer elemento de L y de C

En primer lugar, que se obtiene una referencia al tablero utilizando el mtodo getRule de la clase Game, referencia que se manipula a travs de un tipo de puntero especial dado por la clase ComponentPtr, y una vez obtenido el elemento del juego que representa al tablero, se procede a obtener los colores disponibles (getTiles). A diferencia del DFS que recorre el grafo por sus ramas, el BFS lo debe recorrer por niveles. Se debe, entonces, ir saltando ramas a medida que se recorre el grafo, y por lo tanto el estado que se analiza en un momento no es necesariamente adyacente al prximo a analizar. Esto se convirti en una complicacin a implementar, ya que no se poda reconstruir la solucin como los estados visitados (como se hizo en el DFS). Para solucionar ste problema, se utiliza una lista auxiliar nivel donde se guardan los estados de juego, y otra caminos donde se guarda en paralelo la secuencia de decisiones que llevan a ese estado. stas se inicializan con el estado inicial y con una secuencia vaca respectivamente. Entonces, hasta que se encuentra una solucin se analiza el primer estado en la lista nivel, y si no es solucin se elimina ste y el primer elemento de caminos, despus de agregar al final de la lista sus estados adyacentes. A continuacin, para ver si el estado ya fue generado anteriormente se utiliza el mtodo getVisited. En el DFS se utiliz el mtodo isInPath para este fin, pero aclaramos que no es correcto utilizarlo en este caso porque isInPath consulta si un estado dado se encuentra en la lista de los estados anteriores en los que se hizo update, -8-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

mientras que getVisited consulta en el conjunto de todos los estados por los que pas la simulacin. Si el estado no fue visitado, se procede a asignarle un valor de visitado (booleano) que se activa con el mtodo addVisited, y a analizar los estados adyacentes al mismo. Para recorrer los estados adyacentes se recurre a los colores disponibles ya obtenidos, y uno por uno se ubican en el tablero (a partir del mtodo board->fill), y luego de ejecutar la accin se pasa al estado siguiente del juego utilizando el mtodo update del simulador. Ese estado es entonces agregado a la lista nivel aplicando nivel.push_back(sim.getCurrentState()). A su vez, por cada nuevo estado se agrega al final de caminos la secuencia de tiles que llevaron a ese estado, sabiendo que las mismas sern el primer elemento de caminos mas la decisin que llev desde el primer elemento de nivel hasta ese estado. Para ver si uno de los nuevos estados es un estado solucin, se utiliza el mtodo del simulador para la consulta del estado isGameOver, que se determina si el juego finaliz. En el caso de que el juego terminara, se consulta el resultado de finalizacin con el mtodo getGameOverResult, y si efectivamente se encontr una solucin se retorna la ltima lista agregada a caminos y finaliza el juego. El cdigo del algoritmo discutido implementado es:
bool bfs( GameSimulator & sim, unsigned int & depth, list<BoardController::Tile> & solution){ ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); cout << "---- Detalle de la configuracin del tablero:\n"; list<const GameState* > nivel; list<list<BoardController::Tile> > caminos; nivel.push_back(sim.getCurrentState()); list<BoardController::Tile> vacia; caminos.push_back(vacia); list<BoardController::Tile> tiles; board->getTiles(tiles); list<BoardController::Tile>::iterator tile; cout << *board << endl; while (caminos.front().size() <= depth){ sim.setState(nivel.front()); nivel.pop_front(); if (sim.getVisited(sim.getCurrentState())==0){ sim.addVisited(sim.getCurrentState()); for (tile=tiles.begin();tile != tiles.end();tile++){ if (!Podado(sim,*tile)){ board->fill(*tile); sim.update(); nivel.push_back(sim.getCurrentState()); list<BoardController::Tile> l= caminos.front(); l.push_back(*tile); caminos.push_back(l); if (sim.isGameOver()){ if (sim.getGameOverResult() == GameOverRule::WIN){ cout << "--- Se gano el juego\n\n"; solution=l; return true; } } sim.undoUpdate(); } } } caminos.pop_front(); } return false; }

-9-

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Cuando el algoritmo BFS se ejecuta se hace evidente la alta complejidad temporal de la estrategia; el tiempo que tarda en resolver el juego en notablemente mayor al de otros algoritmos. La razn tambin se puede rastrear al funcionamiento de la estrategia, ya que como recorre el rbol de estados por niveles (siendo cada nivel un movimiento o seleccin de uno de los cuatro colores disponibles), se recorrern 4n estados antes de encontrar una solucin de n pasos o movimientos. Si se considera que la solucin ms eficiente de los tableros propuestos se resuelve en 10 pasos, por lo que para encontrar la solucin se necesitaron analizar ms de un milln de estados, no sorprende que tarde en encontrarla. Por otro lado, sta forma de recorrer el rbol tambin significa que devolver la primera solucin que encuentre en forma vertical, es decir, en la menor cantidad de niveles, por lo que la solucin tendr la menor cantidad de pasos posibles; ser la solucin ptima. Por completitud, se investig la opcin de agregarle una poda a la implementacin de con el fin de recorrer menos estados. sta consiste en slo analizar los movimientos que avancen el estado de juego, y que generen estados nuevos (no repetidos: por esto se pregunta si el estado ya fue visitado o no). Aunque la poda agrega complejidad al anlisis de cada estado, se recorre una cantidad mucho menor de estados.

A Estrella
Adems de los algoritmos ms bsicos de fuerza bruta, en el proyecto se aprovech el contexto del problema para implementar algoritmos de bsqueda ms avanzados que utilizan informacin adicional, especfica a dicho contexto, para orientar la bsqueda de la solucin. Estos algoritmos entran dentro del grupo de algoritmos denominados de bsqueda heurstica, ya que su objetivo es reducir el tiempo de proceso al orientar la exploracin de los estados esperando evaluar una cantidad menor que las estrategias por fuerza bruta. El hecho de que se los llame heursticos se debe a que en general no es posible garantizar una mejora para todos los posibles escenarios. En particular se desarroll en este proyecto el algoritmo de bsqueda heurstica llamado A* (A estrella) probando varias funciones heursticas de evaluacin de estados. El a* para el proyecto se decidi implementar utilizando nicamente una lista de abiertos, la cual aloja registros con la informacin necesarias para que cada heurstica pueda desarrollarlos. Estos registros llamados Elemento de la lista contienen el costo, el estado y una lista con los colores. En primer lugar, carga un registro auxiliar con la configuracin inicial y lo agrega a la lista de abierto, luego le da a la heurstica el primer elemento de la lista_abierta (es decir el de menor costo), para que esta le devuelva una lista con los registros generados. Este registro, que se le pas a la heurstica, se elimina. La lista llamada lista_de_hijos se inserta elemento a elemento, de forma ordenada en la lista_abierta. De esta forma se le continan pasando registros a la heurstica, hasta que el juego se gane. Las tres opciones de a estrella que el usuario ve en pantalla retornan el resultado del a* general, usando diferentes heursticas que recibe como parmetro. El cdigo del a* comn a las tres opciones es el siguiente:
bool astar (GameSimulator & sim, unsigned int & depth, list<BoardController::Tile> & solution, void (*heuristica) (GameSimulator &sim, elemento_de_lista estado, list<elemento_de_lista> &Lista_de_hijos, list<BoardController::Tile> & solution)){ if (sim.isGameOver()) { if (sim.getGameOverResult() == GameOverRule::WIN) { cout << "--- Se gano el juego\n\n" ; return true;}

- 10 -

Anlisis y Diseo de Algoritmos II Cursada 2011 ------------------------------------------------------------------------------------------------------------------------------else { cout << "--- Se perdio el juego\n\n"; return false;} } else { ComponentPtr<BoardController> board(sim.getGame()-> getRule(BOARD)); elemento_de_lista auxiliar; list<elemento_de_lista> Lista_abierta; list<elemento_de_lista> Lista_de_hijos; list<elemento_de_lista>::iterator it_abierto = Lista_abierta.begin(); list<elemento_de_lista>::iterator it_hijos = Lista_de_hijos.begin(); auxiliar.costo=30; auxiliar.estado= sim.getCurrentState(); Lista_abierta.push_front (auxiliar); while (sim.getGameOverResult() != GameOverRule::WIN ){ heuristica (sim,Lista_abierta.front(),Lista_de_hijos, solution); Lista_abierta.pop_front(); it_hijos=Lista_de_hijos.begin(); bool puso=false; for(it_hijos=Lista_de_hijos.begin(); it_hijos!= Lista_de_hijos.end(); it_hijos++){ it_abierto = Lista_abierta.begin(); if (Lista_abierta.size() == 0) Lista_abierta.push_back(Lista_de_hijos.front()); else{ while (it_abierto != Lista_abierta.end()){ if (it_hijos->costo < it_abierto->costo){ Lista_abierta.insert(it_abierto, *it_hijos); it_abierto=Lista_abierta.end(); puso=true; } if (it_abierto != Lista_abierta.end()) it_abierto++; } if (!puso) Lista_abierta.push_back(*it_hijos); } } Lista_de_hijos.clear(); } } return true; }

Ntese que el principio de funcionamiento es similar al del BFS, con la diferencia que al momento de agregar un estado a la lista auxiliar de estados a analizar, ste se inserta ordenadamente segn el costo asignado a cada estado. As se logra dirigir la bsqueda, ya que se van analizando primero los estados que tienen menor costo, o que se supone sern mas eficientes.

Heurstica A* 1
La primer heurstica que se decidi implementar propone analizar la estrategia ms sencilla de resolucin del juego, asignndole menor costo a la funcin que ms casilleros afectara, o que menos casilleros le faltan para pintar todo el tablero del mismo color. De esta forma se podra cuantificar y comparar, a rasgos generales, que tan prctica es la solucin ms evidente. Si esta tcnica se aplicara como un algoritmo Greedy, sera fcil caer en soluciones parciales buenas que no llevan a la mejor solucin general. La - 11 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

implementacin heurstica permite corregir parcialmente este error, al ir almacenando todas las opciones de recorridos en la lista de prioridad (ordenada segn costo) en lugar de adoptar como nica opcin la mejor solucin parcial. De esta forma, si se alcanzara un punto en el cual el costo de las decisiones tomadas hasta el momento supera el de una opcin anterior, se procede a analizar ste camino. Sin embargo, an as la solucin final no es generalmente la ptima. En primer lugar se definen las reglas de juego, la lista de movimientos posibles (tiles), su iterador y un registro auxiliar por medio de los mtodos ya explicados. Luego realiza un set.State del estado pasado por parmetro y pide los colores disponibles mediante el getTiles, quitando el color que ya est establecido. A partir de estos datos, entonces, se procede a crear una lista auxiliar con las coordenadas (o puntos) de los casilleros que perteneces a la mancha de casilleros adyacentes y del mismo color al casillero de inicio. Con sta se evala el costo de la transformacin como la cantidad de casilleros que faltan pintar, o sea, el tamao del casillero (100) menos el tamao de esta mancha (mancha.size()), y se pasan los datos al registro auxiliar que se carga en la lista_de_hijos. A continuacin pregunta si se gano y de haberlo hecho pasa a solution la secuencia con la que se resolvi. Despus se agrega a costo la componente g, dada por el tamao de la lista de colores que se emplearon para resolverlo. La lista_de_hijos mas tarde se intercalar con la lista abierta en funcin de su costo. El cdigo propiamente dicho es el siguiente:
void TransformaMas (GameSimulator &sim, elemento_de_lista estado, list<elemento_de_lista> &Lista_de_hijos, list<BoardController::Tile> & solution){ list<elemento_de_lista> Lista_abierta; ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); list<BoardController::Tile> tiles; list<BoardController::Tile>::iterator it_tiles = tiles.begin(); elemento_de_lista auxiliar; sim.setState(estado.estado); board->getTiles(tiles); tiles.remove(board->getTile(0,0)); cout << "Estado incial:" << endl << *board; bool Visitados[10][10]; for (int i=0;i<10;i++) for(int j=0;j<10;j++) Visitados[i][j]=false; for (it_tiles=tiles.begin(); it_tiles != tiles.end(); it_tiles++){ if (sim.getGameOverResult() != GameOverRule::WIN ){ sim.setState(estado.estado); board->fill(*it_tiles); sim.update(); for (int i=0;i<10;i++) for(int j=0;j<10;j++) Visitados[i][j]=false; list<punto> mancha=Mancha(sim,Visitados); auxiliar.estado = sim.getCurrentState(); auxiliar.secuencia = estado.secuencia; auxiliar.secuencia.push_back(*it_tiles); auxiliar.costo=100-mancha.size(); if (sim.getGameOverResult() == GameOverRule::WIN) solution=auxiliar.secuencia; auxiliar.costo=auxiliar.costo + auxiliar.secuencia.size(); cout << "El costo del hijo es" << auxiliar.costo; Lista_de_hijos.push_front(auxiliar); } } cout << "Lista de hijo:" << Lista_de_hijos.size(); tiles.clear(); }

- 12 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Heurstica A* 2
Para la segunda heurstica se acercamiento ms bien probabilstica. La estrategia consiste en subdividir el tablero en 9 grupos de 4 pxeles, alineados en diagonal a partir de la esquina superior izquierda (casillero inicial), como indica la Imagen 1. En base a los cuatro colores que constituyen los movimientos posibles, existen unas 256 configuraciones para cada uno de estos subgrupos; de los cuales solo el 1,56% de las mismas poseen todos los pxeles del mismo color y un 9,83% tienen a todos de distinto color; el 70,31% estn compuestos por dos colores y el restante 18,75% est formado por configuraciones con tres colores. Imagen 1. Muestra la distribucin de los grupos en el tablero El funcionamiento de la heurstica se basa en las probabilidades que existes que un pixel contagie a otro a travs de los sucesivos cambios de color que implica resolver al diagonal principal. Pero todos los cuadros, en base a su disposicin estarn expuestos a una cantidad distinta de cambio (Tabla 1). En esta tabla se trabaja con el caso particular de la peor configuracin posible, en la que se deban realizar 27 cambios. Las casillas ms cercanas a la diagonal tienen nmeros de cambio bastante altos, lo que hace que sea muy probable Tabla 1. Tabla exposicin al cambio de colores que se terminen contagiando. En la tabla 2 muestran con detalle estas probabilidades mencionadas. En la prctica, sera bastante extrao que se genere esta situacin, y entonces generalmente la diagonal se resuelve sin tener que recurrir a los 27 pasos, lo que ocasiona que se produzcan tambin menos contagios, y en ocasiones queden pixeles independientes luego de haber cubierto la diagonal. Para estas situaciones, la heurstica empieza a valorar la cantidad de filas que se contagiaron completamente, y privilegia aquellas situaciones en las cuales completaron mas filas consecutivas de arriba hacia abajo.

Tabla 2. Probabilidades de contagio luego de 27 cambios

- 13 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

El 100% de las configuraciones pueden resolverse con 3 movimientos, pero para un 67,18 % de las mismas bastan 2 movimientos, un 19% 1 movimiento y cerca del 2 % no requerir ningn cambio. La heurstica entonces se concentra en resolver la diagonal central, ignorando el resto de los casilleros y lo hace de la siguiente manera. Primero, consulta el color del casillero de inicio, y lo guarda. Luego compara el color del casillero 2 y el del 3 (direccionadas como en la imagen 2); si son iguales entre s el programa querr saber si tambin son iguales al 1. Si lo son, pregunta si son iguales al 4, de serlo entonces este grupo, ya est Imagen 2. Disposicin de los pixeles modelo resuelto y se descuentan del total de movimientos presupuestos para el mismo, 3. Ahora, hace que el casillero de inicio pase a ser el 4, trasladndose al siguiente grupo. Repite este proceso hasta nota que se completo la diagonal o hasta que algn color disienta con el patrn. Luego ordena los tableros en funcin de la relacin progreso/costo, y desarrolla el que cree ms conveniente, cargndole cada color y evaluando una nueva apreciacin heurstica. El pseudo cdigo que analiza que costo implica cada paso tiene la siguiente forma:
if (2 = = 3) if (2 = = 1) if (1 = = 4) El casillero 1 pasa a ser el 4 Se descuentan 3 del costo mximo else Descuento 2 else if (2 = = 4) Descuento 2 else Descuento 1 else if (2 = = 1) if (2 = = 4) Descuento 2 else Descuento 1 else if (1 = = 3) if (1 = = 4) Descuento 2 else Descuento 1 else No descuento nada

El cdigo propiamente es el siguiente:


void heuristica_diagonal (GameSimulator &sim, elemento_de_lista estado, list<elemento_de_lista> &Lista_de_hijos, list<BoardController::Tile> & solution){ ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); list<BoardController::Tile> tiles; list<BoardController::Tile>::iterator it_tiles = tiles.begin(); elemento_de_lista auxiliar; sim.setState(estado.estado); board->getTiles(tiles);

- 14 -

Anlisis y Diseo de Algoritmos II Cursada 2011 ------------------------------------------------------------------------------------------------------------------------------tiles.remove(board->getTile(0,0)); for (it_tiles=tiles.begin(); it_tiles != tiles.end(); it_tiles++){ if (sim.getGameOverResult() != GameOverRule::WIN ){ sim.setState(estado.estado); board->fill(*it_tiles); sim.update(); auxiliar.estado = sim.getCurrentState(); auxiliar.secuencia = estado.secuencia; auxiliar.secuencia.push_back(*it_tiles); int x=0, y=0; bool corte=true; auxiliar.costo=30; while ( (x<9) && corte){ if ((board-> getTile(x,y+1))==board-> getTile(x+1,y)){ if ((board-> getTile(x,y+1))==board-> getTile(x,y)){ if ((board-> getTile(x,y))==board-> getTile(x+1,y+1)){ auxiliar.costo=auxiliar.costo-3; x=x+1; y=y+1; } else{ corte=false; auxiliar.costo=auxiliar.costo-2;} } else{ if ((board-> getTile(x,y+1))==board-> getTile(x+1,y+1)){ corte=false; auxiliar.costo=auxiliar.costo-2;} else{ corte=false; auxiliar.costo=auxiliar.costo-1;} } } else{ if ((board-> getTile(x,y+1))==board-> getTile(x,y)){ if ((board-> getTile(x,y+1))==board-> getTile(x+1,y+1)){ corte=false; auxiliar.costo=auxiliar.costo-2;} else{ corte=false; auxiliar.costo=auxiliar.costo-1;} } else { if ((board-> getTile(x,y))==board-> getTile(x+1,y)){ if ((board-> getTile(x,y))==board-> getTile(x+1,y+1)){ corte=false; auxiliar.costo=auxiliar.costo-2;} else{ corte=false; auxiliar.costo=auxiliar.costo-1;} } else corte=false; } } } y=0; while ((corte)&& (sim.getGameOverResult() != GameOverRule::WIN)){ x=0; while ( (x<9) && corte){ if ((board-> getTile(x,y))==board-> getTile(x+1,y)){ auxiliar.costo=auxiliar.costo-0.5; x++;}

- 15 -

Anlisis y Diseo de Algoritmos II Cursada 2011 ------------------------------------------------------------------------------------------------------------------------------else corte=false; } y++; if(y>9) corte=false; } if (sim.getGameOverResult() == GameOverRule::WIN) solution=auxiliar.secuencia; auxiliar.costo=auxiliar.costo + auxiliar.secuencia.size(); Lista_de_hijos.push_front(auxiliar); } } tiles.clear(); }

Lo que hace primero es definir las reglas del juego, junto con una lista de tiles, su iterador y un registro auxiliar. Luego realiza un set.State del estado pasado por parmetro y pide los colores disponibles mediante el getTiles, pero quitando el color que ya est establecido, puesto que con este no se avanzara, haciendo su anlisis un desperdicio. Luego, si an no gan, para cada uno de los colores, hace: - Carga el estado original - Carga el color y actualiza el simulador. - Pasa a auxiliar el estado actual, junto con la secuencia de colores con los que lo resolvi, agregndole el ltimo que cargo. - Con un while, analiza el avance en la diagonal, preguntando sucesivamente si los colores del tablero en ciertas posiciones coinciden mediante la sentencia getTiles referenciado las posiciones x e y que van cambiando a medida que el proceso avanza. Este ciclo cortar por uno de dos motivos; porque no termino de resolverse la diagonal o porque se alcanzo el lmite del tablero. El primer caso se controla mediante una variable bool llamada corte, y el segundo teniendo en cuanta que los entero x e y, sean menores a 9, porque las posiciones de x e y van de 0 a 9. Existe un segundo while, al que solo se accede si no se ha ganado y la diagonal ya fue resuelta; este recorre fila por fila y le resta 0,5 al costo por cada pxel resuelto. La lnea siguiente pregunta si se gano y de haberlo hecho pasa a solution la secuencia con la que se resolvi. Se agrega a costo la componente g, dada por el tamao de la lista de colores que se emplearon para resolverlo. Se carga en la lista_de_hijos, el registro auxiliar. Esta lista luego se intercalara con la lista abierta en funcin de su costo.

Heurstica A* 3
La ltima heurstica implementada es similar a la segunda pero propone mejorar su resultado considerando como mejores a los estados en que la mancha se ha expendido ms filas contiguas, empezando desde la primera. Para esto realiza una tcnica de barrido, a partir de la cual a un costo presupuesto inicial se le descuenta 0,5 por cada casillero que contenga el color del primero. Ni bien encuentra uno discordante, finaliza con el proceso. Este primer anlisis acabar dando con la solucin de manera inevitable, ya que avanza fila a fila, pixel a pixel, a diferencia del a* anterior que pretende completar la diagonal y una vez logrado depende de otro sub-proceso que le indique que situacin es ms favorable (sin ir ms lejos, aquel sub-proceso se rige con el concepto de barrido del tablero).

- 16 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Las primeras lneas definen las reglas y las estructuras que luego se utilizaran. Luego se carga el estado, se piden los colores disponibles, eliminando al establecido por defecto. Por cada uno de los colores disponibles, hace un setState, le carga el color que apunta el iterador y actualiza. Despus carga en auxiliar el estado actual y la secuencia de colores al campo secuencia. Con dos while anidados se asegura que solo termine dado que llego al fin del tablero sin detectar cambio de color, es decir, se gano o que se halla detectado un cambio y la variable corte haya cambiado su valor. Por ltimo rellena el campo costo. Luego de que el for termine, devolver una lista con registros con la informacin necesaria para continuar con el desarrollo. El cdigo de la implementacin de sta heurstica es:
void heuristica_de_barrido (GameSimulator &sim, elemento_de_lista estado, list<elemento_de_lista> &Lista_de_hijos, list<BoardController::Tile> & solution){ ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); list<BoardController::Tile> tiles; list<BoardController::Tile>::iterator it_tiles = tiles.begin(); elemento_de_lista auxiliar; sim.setState(estado.estado); board->getTiles(tiles); tiles.remove(board->getTile(0,0)); for (it_tiles=tiles.begin(); it_tiles != tiles.end(); it_tiles++){ if (sim.getGameOverResult() != GameOverRule::WIN ){ sim.setState(estado.estado); board->fill(*it_tiles); sim.update(); auxiliar.estado = sim.getCurrentState(); auxiliar.secuencia = estado.secuencia; auxiliar.secuencia.push_back(*it_tiles); int x=0, y=0; bool corte=true; auxiliar.costo=30; while (corte){ x=0; while ( (x<9) && corte){ if ((board-> getTile(x,y))==board-> getTile(x+1,y)){ auxiliar.costo=auxiliar.costo-1; x++;} else corte=false; } y++; if(y>9) corte=false; } if (sim.getGameOverResult() == GameOverRule::WIN) solution=auxiliar.secuencia; auxiliar.costo=auxiliar.costo + auxiliar.secuencia.size(); Lista_de_hijos.push_front(auxiliar); } } tiles.clear(); }

Al final, esta heurstica es la que hace un anlisis ms parcial de las tres, enfocndose nicamente en el color del adyacente, y en base a esto sus resultados no son tan buenos, pero su tiempo computacional es muy bajo.

- 17 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Funciones Auxiliares
Para facilitar la referencia a las coordenadas de los casilleros se implement la estructura punto. Punto consta de dos enteros, uno para la coordenada horizontal (r) y otro para la coordenada vertical (s) y en lenguaje C++ tiene la forma
struct punto { int r; int s; };

Y, para facilitar la comparacin entre coordenadas, adems se implemento el operador


bool operator = = (const punto& p1,const punto& p2){ if ((p1.r = = p2.r)&&(p1.s = =p2.s)) return true; return false; }

Por otro lado, para el a estrella fue necesario implementar otra estructura, que sera de la que se arma la lista de prioridades. Esta estructura consta de un estado, un float donde se almacena el costo de dicho estado (criterio por el cual luego se ordena la lista) y una lista secuencia que mantiene registro de los movimientos que llevaron a ese estado desde el inicial.
struct elemento_de_lista { float costo; const GameState* estado ; list <BoardController::Tile> secuencia; };

Tanto para la Heurstica 1 como para la poda del BFS se necesit implementar una funcin que devolviera una lista con las coordenadas (para lo que se uno la estructura punto) de los casilleros que pertenecieran a la mancha. Esta lista, entonces, contiene los casilleros del mismo color que el casillero inicial y que son adyacentes al mismo o a uno adyacente a ste. Para armar sta lista se parte del casillero inicial y se lo agrega a la lista. Luego, se recorre esta lista por medio de in iterador, a su vez agregando al final de la lista los casilleros adyacentes al casillero en cuestin (arriba, abajo, a la derecha o a la izquierda) que contengan el mismo color que el inicial. Se tiene en cuenta que para hacer esto efectivamente es necesario mantener un registro de los casilleros que ya se incluyeron en la lista; esto se hace con una matriz auxiliar booleana de 10x10. El cdigo de esta funcin es el siguiente:
list<punto> Mancha(GameSimulator &sim,bool Visitado[10][10]){ ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); punto coord; coord.r=0; coord.s=0; list<punto> mancha; mancha.push_back(coord); list<punto>::iterator it=mancha.begin(); Visitado[0][0]=true; while(it!=mancha.end()){ int x=(*it).r; int y=(*it).s; if (x>0){ if ((board->getTile(x-1,y)==board-> getTile(0,0))&&(!Visitado[x-1][y])){ coord.r=x-1; coord.s=y; mancha.push_back(coord); Visitado[x-1][y]=true; } } if (y>0){

- 18 -

Anlisis y Diseo de Algoritmos II Cursada 2011 ------------------------------------------------------------------------------------------------------------------------------if ((board->getTile(x,y-1)==board-> getTile(0,0))&&(!Visitado[x][y-1])){ coord.r=x; coord.s=y-1; mancha.push_back(coord); Visitado[x][y-1]=true;} } if (x<9){ if ((board->getTile(x+1,y)==board-> getTile(0,0))&&(!Visitado[x+1][y])){ coord.r=x+1; coord.s=y; mancha.push_back(coord); Visitado[x+1][y]=true; } } if (y<9){ if ((board->getTile(x,y+1)==board-> getTile(0,0))&&(!Visitado[x][y+1])){ coord.r=x; coord.s=y+1; mancha.push_back(coord); Visitado[x][y+1]=true; } } it++; } return mancha; }

Finalmente, para la poda del BFS se implement una funcin que devuelve un valor booleano positivo si el estado analizado avanza el estado de juego (si acerca a la solucin). ste se basa en recorrer el tablero y establecer si entre todos los casilleros adyacentes a la mancha hay alguno del color en cuestin.
bool EsAdy(int x1, int y1, int x2, int y2){ if (((x1==x2)&&((y1==y2+1)||(y1==y2-1)))|| ((y1==y2)&&((x2==x1+1)||(x2==x1-1)))) return true; return false; } bool Pertenece(list<punto> mancha, int x, int y){ list<punto>::iterator it; for (it=mancha.begin();it!=mancha.end();it++) if (((*it).r==x)&&((*it).s==y)) return true; return false; } bool Podado (GameSimulator &sim, unsigned int color) { ComponentPtr<BoardController> board(sim.getGame()->getRule(BOARD)); list<BoardController::Tile> tiles; list<BoardController::Tile>::iterator it_tiles = tiles.begin(); board->getTiles(tiles); bool Visitados[10][10]; for (int i=0;i<10;i++) for(int j=0;j<10;j++) Visitados[i][j]=false; list<punto> mancha=Mancha(sim,Visitados); list<punto>::iterator it; for (int i=0;i<10;i++) for(int j=0;j<10;j++) if (board->getTile(i,j)==color) for (it=mancha.begin();it!=mancha.end();it++) if (EsAdy((*it).r,(*it).s,i,j)) if (!Pertenece(mancha,i,j)) return false; return true; }

- 19 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Interpretacin de los resultados


Comparando las configuraciones iniciales de distintos tableros se discute la calidad de los distintos resultados. Para hacer los resultados de ste anlisis ms representativo se crearon cuatro tableros ms para ser tenidos en cuenta para el anlisis. Aclaramos, tambin, que al momento de comparar se utiliz el BFS sin la poda, ya que no es parte de la consigna del trabajo sino que fue implementada por una cuestin de completitud a la hora de estudiar el BFS.

Tabla 3. Muestra la cantidad de pasos necesario para resolver un tablero.

El promedio de pasos que tienen las soluciones obtenidas mediante DFS es muy alto, cerca del triple de pasos del BFS, que ronda los 10,75. As mismo las heursticas retornan resultados muy buenos aunque en pocos casos la ptima. El grfico cantifica la eficiencia de cada algoritmo en trminos de cantidad de pasos necesarion para resolver el juego. Se puede ver claramente cmo la lnea del DFS se aleja de las dems en la parte superior y las otras se entrelazan en la parte inferior, teniendo al BFS como base (ya que cmo es la solucin ptima, ninguna otra estrategia puede mejorar su resultado). Adems, puede observarse que por la naturaleza del DFS, sus resultados son bastante irregulares marcando picos y depresiones en la grfica, por ello cremos conveniente generar un grfico basado en el promedio de los resultados, para optimizar las apreciaciones cuantitativas (grfico izquierdo).

Ms all de que el tiempo que tarda en ejecutarse sea algo relativamente variable, que depende de las caractersticas de la computadora en la que se ejecuta, no podemos pasar por alto ciertas tendencias; los a*, junto con el DFS tardan dcimas de segundo en dar la respuesta mientras que el BFS tarde en promedio 30,3 segundos, marcando tambin un gran variabilidad entre muestra y muestra, que genera un desvi estndar de 22,85 segundos. - 20 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

El grfico de la derecha refleja la eficiencia relativa a la optimizacin en trminos de tiempo de procesamiento / cantidad de pasos de la solucin. Se destaca del grfico, en particular de la lnea roja que traza el BFS, el amplio rango de valores que presenta; es decir cambia drsticamente entre tablero y tablero, generado por la amplia diferencia de tiempos que conllevan. Una posible explicacin a esta diferencia es que es aleatoria y depende de la posicin en el rbol de estados en el que se encuentra la solucin. Las dems lneas casi no se perciben porque se apoyan prcticamente sobre el eje x, a causa de un tiempo de procesamiento cercano a 0. Por otro lado se plantea que las valoraciones de computadora a computadora de esta relacin son bastante subjetivas y dependen de las posibles aplicaciones, en aquellas que requieran una respuesta con excelencia en la calidad estarn dispuestas a otorgar un mayor tiempo al procesamiento, que aquellas que lo necesiten para una aplicacin de tiempo real. Para adecuar la grfica a las necesidades particulares de cada usuario, slo se necesitara multiplicar los valores del rango por una constante puede. Cabe notar que las todas las muestras fueron tomadas con la mayor equidad de condiciones; siendo la misma computadora y solo con los procesos obligatorios del sistema operativo, adems del propio floodfiller. Las configuraciones de los tableros 5, 6, 7 y 8 fueron generadas de forma aleatoria y tienen la siguiente forma:

- 21 -

Anlisis y Diseo de Algoritmos II Cursada 2011 -------------------------------------------------------------------------------------------------------------------------------

Conclusiones
Reconocemos que en el transcurso del trabajo, a medida que se investigaban los distintos mtodos de resolucin de un problema (el juego), cambiamos el enfoque con el que se resolva el juego. Al visualizar la secuencia de colores y los estados a los que llevan como un grafo, tanto en el DFS como en el BFS vemos que se llega a soluciones ajenas a nuestra forma de razonar; por ejemplo, sera muy difcil (prcticamente imposible) encontrar una solucin ptima en forma manual sin conocer el tablero de antemano, e inconcebible elegir colores que no cambian el tablero como lo hace el DFS. Rescatamos que este enfoque computacional sera muy til para problemas cuya solucin escapa nuestras habilidades. Las heursticas, en cambio, se acercan ms a cmo resolvemos nosotros el juego en forma manual. Vemos que son considerablemente menos costosas que los algoritmos de fuerza bruta y pueden dar soluciones igual de eficientes o muy aproximados. Desde este punto de vista, apreciamos la utilidad de ste tipo de algoritmos de bsqueda avanzada, tanto sobre los de bsqueda exhaustiva como sobre los algoritmos greedy. Por otro lado, en primeras instancias subestimamos el tiempo que tardara la resolucin de los algoritmos por tratarse de un tablero chico y tener computadoras actuales. Sin embargo, particularmente en el BFS, nos sorprendi experimentar directamente el retraso que puede generar un algoritmo que debe visitar tantos estados. Nos sirvi, adems, para visualizar mejor el concepto de complejidad temporal que estudiamos en clase. Un detalle que resulta interesante es cmo las graficas de la eficiencia temporal del BFS y la de cantidad de pasos del DFS tienen cierta semejanza, y esto nos hace pensar que cada tablero conlleva una complejidad intrnseca que para el DFS le hace desperdiciar muchos o pocos cambios y de manera seudo-simtrica al BFS le conlleva un mayor o menor tiempo de procesamiento.

Referencias
David Arthur, Raphal Cliord, Markus Jalsenius, Ashley Montanaro, and Benjamin Sach. The Complexity of Flood Filling Games, Department of Computer Science, University of Bristol, UK http://www.cs.bris.ac.uk/~montanar/papers/floodit.pdf Miran, Kim. Solving Flood Filling Games with Genetic Algorithms, Department of Computer Science, University of Nevada, Reno http://www.cse.unr.edu/~mirank/report/paper.pdf

- 22 -

También podría gustarte