Sei sulla pagina 1di 11

Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto

algoritmo de búsqueda primero en 8-956-675 Torres, Greg


anchura para la solución del 8 puzzle.
1 INTRODUCCIÓN.
Primero veremos los mecanismos de búsqueda a ciegas en un 8 puzzle y luego veremos la
búsqueda en profundidad sin información. La búsqueda a ciegas es aquella que si bien
realiza la búsqueda utilizando los operadores (acciones) disponibles, no utiliza ningún
conocimiento sobre el dominio del problema La búsqueda a ciegas no utiliza conocimiento o
información específica del dominio del problema.
8-Puzle consiste en un tablón cuadrado (3x3) en el que hay situados 8 bloques cuadrados
numerados (con lo cual se deja un agujero del cuerpo de un bloque). Un bloque pegado al
hueco puede deslizarse hacia él. El jugueteo consiste en trocar una posición original en el sitio
final cualquiera, mediante el arrastre de los bloques. Este jugueteo está basado en el 15-
Puzzle, inventado por Sam Loyd en 1870, uno de los más grandes creadores de acertijos
que han existido.
Este trabajo práctico tiene como objetivo representar la solución de 8-puzzle a través de
espacios de estados, para encontrar las soluciones posibles, también la implementación de
los algoritmos de búsqueda y la evaluación del comportamiento de los algoritmos para las
diferentes entradas o estados iniciales, contando los nodos analizados y el largo de la
búsqueda.
.

2 TEORIA DE PILA O STACK EN C++ STL.


2.1 Introducción.
Las pilas son un tipo de adaptadores de contenedor con el tipo de trabajo LIFO(Last
In First Out), donde se agrega un nuevo elemento en un extremo y (arriba) un
elemento se quita de ese extremo solamente.

2.2 Concepto
A continuación, se exponen una serie de conceptos relativos a la Teoría de pilas
necesarios para este documento.
Las funciones asociadas con stack son:
• empty() – Devuelve si la pila está vacía – Complejidad de tiempo : O(1)
• size() – Devuelve el tamaño de la pila – Complejidad de tiempo : O(1)
• top() – Devuelve una referencia al elemento superior más de la pila –
Complejidad de tiempo : O(1)
• push(g) – Añade el elemento 'g' en la parte superior de la pila – Complejidad
de tiempo : O(1)
• pop() – Elimina el elemento más alto de la pila – Complejidad de tiempo : O(1)

3 ANÁLISIS DEL PROBLEMA.


3.1 Problema por resolver
El Puzzle deslizante (Sliding-Puzzle en inglés) o 8-puzzle en su versión 3x3 es un
rompecabezas inventado y popularizado por Noyes Palmer Chapman en la década de 1870.
Se juega en una cuadrícula de 3 por 3 con 8 bloques cuadrados etiquetados del 1 al 8 y un
cuadrado en blanco. Tu objetivo es reorganizar los bloques para que estén en orden.
Inteligencia Artificial Semestre I, 2020 1
1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.
3.2 Estado inicial.
Iniciando el “Juego” podemos añadirle varias posiciones como inicio, debemos aclarar que
el programa está diseñado para que no se pueda introducir números menores a 0 o mayores
a 8.

3.3 Operadores
Movimientos de fichas utilizando el espacio en blanco (ficha con valor "0")

• Mover espacio hacia arriba


• Mover espacio hacia abajo
• Mover espacio hacia la derecha
• Mover espacio hacia la izquierda

Descripción del operador "Mover espacio hacia arriba"


• Aplicabilidad: Es aplicable a estados que no tengan espacio en la primera fila
• Función de transformación: Intercambio de las posiciones del espacio y de la ficha que
está encima de éste.

Descripción del operador "Mover espacio hacia abajo"


• Aplicabilidad: Es aplicable a estados que no tengan espacio en la última fila
• Función de transformación: Intercambio de las posiciones del espacio y de la ficha que
está debajo de éste.

Descripción del operador "Mover espacio hacia la derecha"


• Aplicabilidad: Es aplicable a estados que no tengan espacio en la última columna.
• Función de transformación: Intercambio de las posiciones del espacio y de la ficha que
está a la derecha de éste.

Descripción del operador "Mover espacio hacia la izquierda"


• Aplicabilidad: Es aplicable a estados que no tengan espacio en la primera columna.
• Función de transformación: Intercambio de las posiciones del espacio y de la ficha que
está a la izquierda de éste
3.4 Meta
Terminando el “Juego” tenemos que dependiendo lo que el usuario decida cual quiere que
sea su meta o final, el programa llegara a él, recordando las condiciones que solo se podrá
en cada posición poner desde el numero 0 hasta el número 8, en nuestro caso añadimos el
orden que vemos en el estado de inicio y que si no se mira de una manera gráfica, en el
estado meta si se logra apreciar mejor.

Inteligencia Artificial Semestre I, 2020 2


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.

Ilustración 1: Estado Meta 1.1 Ilustración 2: Estado Meta 1.2

3.5 Función coste.


En la función del coste dependerá del estado de inicio como en el estado meta, en nuestro
caso nuestro coste en la tabla desde la Ilustración 1: Estado Inicio 1.1 hasta la Ilustración 3:
Estado Meta 1.1 tenemos que el coste es de 19 como se puede apreciar en la Ilustración 5
12
Ilustración 3

Inteligencia Artificial Semestre I, 2020 3


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.
3.6 Espacio de estado

Inteligencia Artificial Semestre I, 2020 4


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.
4 ALGORITMO IMPLEMENTADO.
4.1 Primero en profundidad

La búsqueda primero en profundidad consiste en buscar verticalmente es decir, el nodo


raíz se expande , luego el hijo es expandido, a los siguientes de manera vertical y por
la izquierda, en caso de que el nodo este repetido se pasa al siguiente nodo de la
derecha, esto se realiza hasta terminar en el último nodo de esa rama. Se puede decir
que tiene una estructura de cola LIFO.

4.1.1 Descripción

Dado un grafo o árbol y un vértice inicial s, una búsqueda en anchura procede explorando
las aristas en el grafo para encontrar todos los vértices en G para los cuales hay una
ruta a partir de s. Lo notable de una búsqueda en anchura es que encuentra todos los
vértices que estén a una distancia k de s antes de encontrar cualesquiera vértices que
estén una distancia k+1. Una buena manera de visualizar lo que hace el algoritmo de
búsqueda en anchura es imaginar que está construyendo un árbol, un nivel del árbol a
la vez. Una primera búsqueda en anchura agrega todos los hijos del vértice inicial antes
de que comience a descubrir a alguno de los nietos.

4.1.2 Estrategia.
Esta búsqueda expande siempre el nodo más profundo en el árbol. Una vez que un
nodo no puede ser expandido se vuelve hacia atrás para buscar otro nodo a ser
expandido.
Se expande la raíz, se toma un nodo de los recién expandidos (supongamos el
primero) se expande éste, luego nuevamente se toma un nodo de estos últimos, y así
hasta llegar a un nodo que es la meta o no se pueda expandir más. En este último
caso se retrocede (backtracking) hasta el nodo más reciente que tenga una alternativa
sin explorar.
Sigamos nuestro ejemplo anterior con profundidad primero: Se expande A que es la
raíz del árbol, luego tenemos B y C como los nuevos nodos. Elegimos C para expandir,
que genera D y F. Ahora a diferencia de ancho primero (donde deberíamos elegir B)
elegimos uno de los nuevos (D o F), supongamos D, este genera a E. Ahora elegimos
a E (de los últimos generados) y finalizamos porque es la meta.
En el proceso descrito hemos obviado los nodos repetidos, es decir si ya fue visitado
no lo generamos (por ejemplo cuando expandimos C obviamos A). La siguiente figura
muestra el árbol de búsqueda para profundidad primero.

Inteligencia Artificial Semestre I, 2020 5


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.

Ilustración 4: Estrategia se búsqueda en profundidad

5 DOCUMENTACIÓN DEL CÓDIGO FUENTE


5.1 Visión general
Nombre de archivo Descripción
main.c Define el procedimiento principal del programa. Esta incluye
nuestra implantación para la resolución del puzzle.
nodo.h Define la estructura de datos para representar un nodo del
árbol del juego, que contiene el estado del juego y otra
información. Las operaciones de nodo también son definidas
aquí
estado.h Define la estructura de datos para representar un estado del
juego Las operaciones en los estados también están definidas
aquí
io.h Contiene funciones relacionadas con entrada / salida
operaciones
Inteligencia Artificial Semestre I, 2020 6
1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.

5.2 Estructuras de datos y operaciones

5.2.1 Estados

Un estado del juego es una configuración del tablero 3X3 con su respectivo movimiento
del espacio, con un número que van de 1 al 8. El estado es como una representación
del juego.

typedef struct Estado


{
mov accion;
char tablero[3][3];
} Estado;
Funciones Descripción
Estado* crearEstado(Estado* Crea y devuelve un nuevo estado derivado del
estado, mov mov) argumento el estado antecesor

5.2.2 Operadores

Los operadores son todas las acciones disponibles de acuerdo con la mecánica del
juego. En el caso de cualquier n- normal juego de rompecabezas, las posibles acciones
son arriba, abajo, izquierda y derecha.
typedef enum mov
{
ARRIBA, ABAJO, IZQ, DERECHA,
NO_APLICA
} mov;
5.2.3 Nodos
Un nodo constituye nuestro árbol de búsqueda que es diferente a un árbol binario
llegándose a parecer más a un grafo. Contiene información sobre sus padres, hijos,
estados.
Cómo se puede ver, el nodo está compuesto con por un estado en concreto, un nodo
padre y la lista de los Hermanos que tiene ese hijo.
struct Nodo
{
unsigned int d;
Estado* estado; //estado designado para un nodo
Nodo* Padre;
Nodo* listahijo; //lista de nodos secundarios
};
Funciones Descripción

Inteligencia Artificial Semestre I, 2020 7


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.
Nodo* crearNodo(int d, Estado* s, Nodo* p) Crea y devuelve un nuevo
nodo estado s y nodo
principal p.
std::vector<Nodo*> optenerlistahijo(Nodo* Expande el nodo p y
padre, std::vector<Estado*>s) devuelve una lista de
elementos secundarios
nodos con su costo h
calculado basado en el
estado del objetivo g

5.2.4 Ruta de la solución


Esta estructura crea una lista de acciones para ejecutar para alcanzar el objetivo, es
decir, la ruta de la solución. La implementación utiliza una lista vinculada individualmente
typedef struct RutaSolucion
{
mov accion;
struct RutaSolucion *sig;
} RutaSolucion;
Funciones Descripción
void imprimirSolucion(struct RutaSolucion* Esta función interpreta
path)) instrucciones numéricas del
movimiento a realizar,
* es su contraparte verbal
que se mostrará en la
pantalla.
5.3 Contadores globales
Según las instrucciones, el programa debe poder recopilar e imprimir la secuencia de
movimientos correspondiente a la solución y las siguientes estadísticas:
• número total de nodos expandidos
• número total de nodos generados
• longitud de la ruta de solución (número de movimientos)
• secuencia de movimientos correspondientes a la solución (por ejemplo, izquierda,
derecha, arriba, abajo)
• nsigned int nodosExpandidos; //número de nodos expandidos
• unsigned int nodosGen; //número de nodos generados
• unsigned int solucionTam; //número de movimientos en solución
• double runtime; //tiempo transactualido (en milisegundos)

Inteligencia Artificial Semestre I, 2020 8


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.
6 PRUEBA DE ESCRITORIO Y EXPLICACION DEL
ALGORITMO.

std::stack<Nodo*> pila;
std::vector<Nodo*> listahijos;
std::vector<Estado*> hijosVistos;
Nodo* nodo = (struct Nodo*)malloc(sizeof(Nodo));
//iniciar temporizador almacenara los hijos o
clock_t inicio = clock(); nodos que se expanden
y que sean un
//inicializar la pila con el nodo raíz del árbol de búsqueda movimiento valido
nodo = crearNodo(0, &estado_inicial, NULL);
hijosVistos.push_back(&estado_inicial);
pila.push(nodo); pila que almacenara los
nodos
//mientras haya un nodo en la pila para expandir
while (!pila.empty())
{ bucle casi infinito
//abre el último nodo (pila) de la pila
nodo = pila.top();
pila.pop();
//si el estado del nodo es el estado objetivo
if (estadoHallado(nodo->estado, meta))
quieta el primer break;
elemento //de lo contrario, expande el nodo y actualiza el contador de nodos
expandidos
if (!hijosVistos.empty())
{
listahijos = optenerlistahijo(nodo, hijosVistos); Genera los hijos y
++nodosExpandidos; almacenara en el vector
} listahijos, también
//agrega los hijos del nodo a la cola comparara los estados
for (int i = 0; i < listahijos.size(); i++)
almacenados en el
{ vector hijosVisitos
if (estadoHallado(listahijos.at(i)->estado, meta)) {
nodo = listahijos.at(i);
break; agrega en la pila los
} hijos generados y
else almacena en el vector
{ los mismos en
pila.push(listahijos.at(i)); hijosVistos
hijosVistos.push_back(listahijos.at(i)->estado);
}
}
}

Inteligencia Artificial Semestre I, 2020 9


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.

estado pila estado actual estadoH


entrada allado
(!pila.empty()
False

nodo = pila.top();
pila.pop(); False

if (estadoHallado(nodo->estado, meta))
= False
ciclo
listahijos = optenerlistahijo(nodo,
hijosVistos);
++nodosExpandidos;

pila.push(listahijos.at(i));

hijosVistos.push_back(listahijo
s.at(i)->estado);

7 RESULTADOS

Inteligencia Artificial Semestre I, 2020 10


1IL134
Asignación # 7: Implementación del 9-734-691 Sánchez, Ernesto
algoritmo de búsqueda primero en 8-956-675 Torres, Greg
anchura para la solución del 8 puzzle.

Ilustración 5: La solución de acorde a el estado inicia y final.

La descripción de las operaciones que se realizó para hallar la solución se ve que se tiene
una cantidad de nodos generados de más de nodos que en soluciones anteriores.

8 CONCLUSIONES.
DFS no es ni óptimo ni completo. No es óptimo porque si existe más de una solución, podría
encontrar la primera que estuviese a un nivel de profundidad mayor, y para ver que no es
completo es necesario irse a ejemplos en los que el espacio de búsqueda fuese infinito
También se tuvieron que implementar una especie de tope o límite para parar la iteración.

Inteligencia Artificial Semestre I, 2020 11


1IL134

Potrebbero piacerti anche