Anda di halaman 1dari 12

AGENTES INTELIGENTES Al igual que ocurre con la propia definicin de la IA, se pueden encontrar propuestas en la literatura un gran nmero

de definiciones del concepto de agente, sin que ninguna de ellas haya sido plenamente aceptada por la comunidad cientfica, siendo quizs la ms simple la de Russell [Russell1996], que considera un agente como una entidad que percibe y acta sobre un entorno (ver figura 1). Basndose en esta definicin, se pueden caracterizar distintos agentes de acuerdo a los atributos que posean (y que van a definir su comportamiento) [Botti1999] para resolver un determinado problema.

Ambiente: Fabrica de Produccin de Autos 3. Agente inteligente de motor de Base de Datos Percepciones: Tareas Predefinidas por el DBA, Acciones de los Usuarios. Acciones: Backups, realizar informes, enviar mensajes. Metas: Seguridad, Automatizacin, Auditora Ambiente: Grupo de Usuarios 4. Asesor Interactivo de Ingls Percepciones: Palabras escritas a mquina. Acciones: Ejercicios impresos, sugerencias y correcciones. Metas: Que el estudiante obtenga la mxima calificacin en una prueba. Ambiente: Grupo de Estudiantes

Figura 1 Estructura de los agentes inteligentes Agente = Programa agente + Arquitectura, donde: El programa agente ser una funcin que implementar la transformacin (mapping) de secuencias de percepciones en acciones. La arquitectura ser un ordenador que se ocupar de que las percepciones lleguen al programa y las acciones lleguen a los efectores La IA se ocupa del diseo del programa agente. 2. Antes de disear un programa agente tenemos que conocer los distintos elementos que caracterizan al agente: Percepciones posibles Acciones posibles Metas. Medida de desempeo u objetivos que debe lograr Ambiente. Tipo de entorno en el que va a operar Ejemplos Agentes Inteligentes 1. Videojuego de Estrategia Percepciones: Acciones del oponente ingresados por consola. Acciones: Ataques, Defensa, Administracin de recursos Metas: Derrotar al oponente o diezmarlo. Ambiente: Jugadores, Escenarios de combate 2. Autmata ensamblador de partes Percepciones: Pixels de intensidad variable Acciones: Recoger partes y ensamblarlas. Metas: Ensamblar correctamente las partes del auto.

8-Puzzle con A* 1. Objetivo El objetivo del proyecto es el de resolver el problema del 8-Puzzle con un algoritmo informado de bsqueda de caminos especialmente A* Descripcin del problema

El problema de 8-Puzzle consiste, como se muestra la figura 1, en tablero de 3 X 3, el cual contiene 8 bloques cuadrados numerados (del 1 al 8) y un cuadrado vaco (En nuestra representacin ser numerado con 0). Los cuadrados adyacentes al espacio vaco pueden moverse a ese espacio. El objetivo es alcanzar un estado meta. 3. Estado

Representacin mediante matriz E (cada casillero corresponde a un elemento en la matriz), y vector (del casillero vaco) (E (X,Y)) 4. Estado inicial

Cualquier combinacin de piezas en tablero puzzle

Sacamos de la cola de prioridad el elemento con menor prioridad (menor f(n)) expandimos su nodos de la misma manera antes descrita. De esta manera, el rbol se va expandiendo por los nodos que representan el camino hacia el nodo meta pero con el menor coste. 5. Espacio de estados 10. Heurstica

Todas las configuraciones posibles de las piezas en el tablero puzzle. 6. Costo del camino:

Cada movimiento o paso, tiene un costo de uno (1), por lo tanto el camino desde un estado inicial a un estado meta es igual al nmero de pasos (o movimientos) que se dan para alcanzar el estado meta

La implementacin del algoritmo A* se ha realizado haciendo uso de dos heursticas diferentes, las cuales permiten que para un mismo nodo, el valor del costo estimando del estado de dicho nodo hacia el estado meta, tenga valores diferentes. De esta manera, las heursticas implementadas son: * H1: Heurstica que dado un estado inicial y un estado meta para el 8-puzzle, contabiliza el nmero de casillas del 1 al 8 que no se encuentran en su posicin correcta, sin tomar en cuenta la casilla vaca (considerada con valor 0) Es decir, si: estado _ inicial = 213506487 estado _ meta = 123456780

7.

Estado final

Es el estado al que se debe llegar para terminar el juego

8.

Reglas del juego H1 = 1 +1 + 0 + 1+ 0 + 0 +1 + 0 + 1 = 5 Esto debido a que las casillas 2,1,5,4,7 en estado _ inicial no se encuentran en su posicin adecuada respecto a estado _ meta. El costo mximo para alcanzar la meta aplicando H1 es 8, por lo tanto es admisible.

* H2: Heurstica que dado un estado inicial y un estado meta para el 8-puzzle, contabiliza la suma total de distancias mnimas de cada casilla hacia su posicin correcta, es decir se aplica la distancia total de Manhattan. 9. A* aplicado al problema del 8 puzzle El algoritmo A* tambin puede solucionar ste problema, incluso de una manera mucho ms ptima (en tiempo y en espacio) comparada con las soluciones ofrecidas por los algoritmos de bsqueda no informada. Entonces partiremos nuevamente de un determinado estado inicial al cual encontramos su funcin f(n), y luego expandimos, generando nuevos nodos hijos. Cada uno de estos nodos hijos son encolados en una cola de prioridad, tomando como prioridad el valor de f(n) de cada nodo generado. Es decir, si: estado _ inicial = 215387046 estado _ meta = 123456780 H2 = 1 +1 + 2 + 3+ 1 + 3 +0 + 2 + 1 = 14

Teniendo como estado meta a 123456780, el costo mximo para alcanzar la meta aplicando H2 es 14, por lo tanto esta heurstica tambin es admisible.

A*(H1) Estado inicial Nodos generados Nodos en memoria Mximo nivel del rbol Nivel en que halla la solucin Encuentra la solucin 1463 1463 12 12 si A*(H1) Estado inicial Nodos generados Nodos en memoria Mximo nivel del rbol Nivel en que halla la solucin Encuentra la solucin 3603 3603 13 13 si A*(H1) Estado inicial Nodos generados Nodos en memoria Mximo nivel del rbol Nivel en que halla la solucin Encuentra la solucin 28 9 3 no A*(H1) Estado inicial Nodos generados Nodos en memoria Mximo nivel del rbol Nivel en que halla la solucin Encuentra la solucin 48 19 8 8 si

blanco struct nodo *sig;//apunta al nodo siguiente }; A*(H2) 435206718 void pide_estado(struct nodo **g); 329 void A_asterisco(struct nodo **g,struct nodo **f); 329 struct nodo *expansion(struct nodo *g,int d); 12 void inserta(struct nodo **e,struct nodo **n); 12 void borrar(struct nodo **e); struct nodo *evalua_nodo(struct nodo **e,struct nodo si **f);//se usa el metodo de n de casillas mal colocadas void ensena_graf(const struct nodo *g); A*(H2) void retorn_x_y(const struct nodo **f,unsigned short int 345016728 *i_fin, 614 unsigned short int *j_fin,unsigned short int num); 614 13 void coge_ini(struct nodo **g); 13 void coge_fin(struct nodo **g); si void pide_estado(struct nodo **g) { A*(H2) struct nodo *nuevo; 802143765 short int i,j,a_i,a_j; unsigned 132 132 if(!(nuevo=(struct nodo *)malloc(sizeof(struct nodo)))) printf("no queda memoria \n"); 11 else 11 { printf(" si Mete un 0 en la posicion en blanco \n"); for(i=0;i!=MAX_L;i++) for(j=0;j!=MAX_L;j++) { A*(H2) printf("\n Mete el n de la posicion [%d,%d]=",i,j); 053216478 scanf("%d",&nuevo->puzle[i][j]); 55 if(nuevo->puzle[i][j]==0) 55 { 8 a_i=i; 8 a_j=j; } } si nuevo->blanco[0]=a_i; nuevo->blanco[1]=a_j; } nuevo->ant=NULL; nuevo->sig=NULL; *g=nuevo; }

11. Algoritmo con A* codificado en c++ #include<stdio.h> #include<stdlib.h> #include<math.h> #define MAX_L 3

struct nodo{ struct nodo *ant;//apunta al nodo anterior unsigned short int puzle[MAX_L][MAX_L];//contiene el puzle unsigned short int blanco[2];//tiene la posicion x e y donde esta el

void A_asterisco(struct nodo **g,struct nodo **f) { int terminado=0; struct nodo *expan=NULL,*aus=NULL,*nuevo=NULL; while(! terminado)

{ if((*g)->blanco[1]!=MAX_L-1) { nuevo=expansion(*g,1); inserta(&expan,&nuevo); } if((*g)->blanco[1]!=0) { nuevo=expansion(*g,2); inserta(&expan,&nuevo); } if((*g)->blanco[0]!=MAX_L-1) { nuevo=expansion(*g,3); inserta(&expan,&nuevo); } if((*g)->blanco[0]!=0) { nuevo=expansion(*g,4); inserta(&expan,&nuevo); } aus=evalua_nodo(&expan,f); if(aus==NULL)//fin del proceso { terminado=1; inserta(g,f);//inserta en el grafo el nodo final } else inserta(g,&aus); borrar(&expan); } } struct nodo *expansion(struct nodo *g,int d) { unsigned short int aus=0,i,j; struct nodo *n; if(!(n=(struct nodo *)malloc(sizeof(struct nodo)))) printf("no queda memoria \n"); else { n->sig=NULL; n->ant=NULL; for(i=0;i!=MAX_L;i++) for(j=0;j!=MAX_L;j++) n->puzle[i][j]=g->puzle[i][j]; i=g->blanco[0]; j=g->blanco[1]; n->blanco[0]=i; n->blanco[1]=j; if(d==1)//movimiento del 0 a la derecha {

aus=n->puzle[i][j+1]; n->puzle[i][j+1]=0; n->blanco[0]=i; n->blanco[1]=j+1; } else if(d==2)//movimiento del 0 a la izquierda { aus=n->puzle[i][j-1]; n->puzle[i][j-1]=0; n->blanco[0]=i; n->blanco[1]=j-1; } else if(d==3)//movimiento del 0 abajo { aus=n->puzle[i+1][j]; n->puzle[i+1][j]=0; n->blanco[0]=i+1; n->blanco[1]=j; } else if(d==4)//movimiento del 0 arriba { aus=n->puzle[i-1][j]; n->puzle[i-1][j]=0; n->blanco[0]=i-1; n->blanco[1]=j; } n->puzle[i][j]=aus; } return n; } void inserta(struct nodo **e,struct nodo **n) { if(*e != NULL) { (*e)->sig=*n; (*n)->ant=*e; (*n)->sig=NULL; } *e=*n; *n=NULL; } void borrar(struct nodo **e) { struct nodo *borra; while(*e != NULL) { borra=*e; *e=(*e)->sig; free(borra); } }

struct nodo *evalua_nodo(struct nodo **e,struct nodo **f)//se usa el metodo de n de casillas mal colocadas { struct nodo *p_mejor=NULL,*p_mejor_aus=NULL; unsigned short int i,j,mal,mal_aus=0,mejor=999,opcion,i_f,j_f; while((*e) != NULL) { mal=0; for(i=0;i!=MAX_L;i++)//comparacion de los nodos for(j=0;j!=MAX_L;j++) if(((*e)->puzle[i][j] != (*f)->puzle[i][j]) && ((*e)>puzle[i][j] != 0)) {////se aplica Manhatan retorn_x_y(f,&i_f,&j_f,(*e)->puzle[i][j]); mal=mal+(abs(i-i_f)+abs(j-j_f)); } if(mal < mejor) { mejor=mal; p_mejor=*e;// el mejor nodo } else if(mal == mejor) { mal_aus=mal; p_mejor_aus=*e; } *e=(*e)->ant; } opcion=0; if((mejor==mal_aus) && (mejor != 0))// en el caso de que halla 2 nodos posibles { printf("\n\nPROBLEMA! Hay dos nodos con solo %d casilla mal colocadas",mejor); printf("\n Pulse ( 1 ) o ( 2 ) para elegir uno de los dos nodos al azar --> "); scanf("%d",&opcion); fflush(stdin); } if(opcion==2)// en el caso de que halla 2 nodos posibles p_mejor=p_mejor_aus; if(mejor==0)//fin del proceso return NULL; else { if(p_mejor->sig != NULL)

{ p_mejor->sig->ant=p_mejor->ant; p_mejor->sig=NULL; } if(p_mejor->ant != NULL) { p_mejor->ant->sig=p_mejor->sig; p_mejor->ant=NULL; } printf("\n se escoge este"); ensena_graf(p_mejor); return p_mejor; } } void retorn_x_y(const struct nodo **f,unsigned short int *i_fin, unsigned short int *j_fin,unsigned short int num) {///se pasan i_fin y j_fin por referencia unsigned short int i,j; for(i=0;i!=MAX_L;i++)//comparacion de los nodos for(j=0;j!=MAX_L;j++) if((*f)->puzle[i][j] == num) { *i_fin=i; *j_fin=j; } }

void ensena_graf(const struct nodo *g) { unsigned short int i,j,cont_nodo=0; for(;g->ant != NULL;g=g->ant);/// me posiciono en el primer nodo para luego sacar la lista /// en el orden correcto while (g != NULL)/// saco el contenido de la lista { cont_nodo++; printf("\n NODO %d",cont_nodo); for(i=0;i!=MAX_L;i++) { printf("\n"); for(j=0;j!=MAX_L;j++) printf("[%d,%d]=%d <> ",i,j,g->puzle[i][j]); } g=g->sig; } } void coge_ini(struct nodo **g)/// para coger el nodo inicial sin meterlo por teclado { struct nodo *nuevo;

if(!(nuevo=(struct nodo *)malloc(sizeof(struct nodo)))) printf("no queda memoria \n"); else { nuevo->blanco[0]=1; nuevo->blanco[1]=2; nuevo->puzle[0][0]=1; nuevo->puzle[0][1]=2; nuevo->puzle[0][2]=3; nuevo->puzle[1][0]=6; nuevo->puzle[1][1]=4; nuevo->puzle[1][2]=0; nuevo->puzle[2][0]=8; nuevo->puzle[2][1]=7; nuevo->puzle[2][2]=5; } nuevo->ant=NULL; nuevo->sig=NULL; *g=nuevo; } void coge_fin(struct nodo **g)/// para coger el nodo final sin meterlo por teclado { struct nodo *nuevo; if(!(nuevo=(struct nodo *)malloc(sizeof(struct nodo)))) printf("no queda memoria \n"); else { nuevo->blanco[0]=1; nuevo->blanco[1]=1; nuevo->puzle[0][0]=1; nuevo->puzle[0][1]=2; nuevo->puzle[0][2]=3; nuevo->puzle[1][0]=8; nuevo->puzle[1][1]=0; nuevo->puzle[1][2]=4; nuevo->puzle[2][0]=7; nuevo->puzle[2][1]=6; nuevo->puzle[2][2]=5; } nuevo->ant=NULL; nuevo->sig=NULL; *g=nuevo; }

\n\n"); printf("\n PULSE 1- Si desea meter el contenido de los nodos por teclado"); printf("\n PULSE 2- Si desea usar los nodos del ejemplo de clase \n"); do scanf("%d",&opcion); while ((opcion!=1) && (opcion!=2)); if (opcion==1) { printf("\n Introduce la tabla del estado inicial \n"); pide_estado(&grafo); printf("\n Introduce la tabla del estado final \n"); pide_estado(&final); } else { coge_ini(&grafo); coge_fin(&final); } A_asterisco(&grafo,&final);///realiza el proceso printf("\n\n\n PROCESO TERMINADO, ESTE ES EL CAMINO HASTA LA SOLUCION"); ensena_graf(grafo); } 8-Reinas 1. Objetivo El objetivo del proyecto es el de resolver el problema de las 8 reinas con un algoritmo informado de bsqueda de caminos especialmente A* Este problema consiste en colocar 8 reinas en un tablero de ajedrez sin que se ataquen. Una reina puede moverse en el tablero arriba, abajo, izquierda, derecha y en diagonal cualquier nmero de casillas. Una posibilidad es lograr una solucin de manera incremental, acercndose a la meta poco a poco siguiendo una serie de decisiones locales basadas en la informacin obtenida durante el proceso. Hay que asegurarse que la secuencia de transformaciones sea sistemtica, para no generar configuraciones repetidas y no excluir configuraciones deseables. Por ejemplo, el hecho de que pueda haber solo una reina por columna nos reduce el nmero de alternativas con menos de 8 en cada rengln. El hecho de que la bsqueda se pueda sistematizar esta forma es que no nos podemos recuperar de violaciones a restricciones mediante operaciones futuras. Significa que si violamos una restriccin no podemos seguir aadiendo ms reinas para rectificarla. El espacio de estados donde se realizar el juego ser muy grande, lo que puede provocar que igual no podamos apreciar toda la eficiencia de las heursticas. El

void main() { struct nodo *grafo=NULL,*final=NULL; unsigned short int opcion; printf("\n\n Manhatan Metodo A* con estimacion heuristica

8 puzzle tiene hasta 4 nodos hijos en cada posible movimiento, mientras que el problema de las 8-reinas ya en el primer movimiento, en un tablero 8x8 implica 64 posibles opciones. 2. Descripcin del problema El problema de las ocho reinas se trata de un acertijo en el que se colocan ocho reinas sin que se amenacen. En el juego de ajedrez la reina amenaza a aquellas fichas que se encuentren en su misma fila, columna o diagonal. Las 8 reinas consisten en colocar sobre un tablero de ajedrez ocho reinas sin que estas se den jaques entre ellas. Para resolver este problema emplearemos un esquema vuelta atrs (o Backtracking). La definicin formal del problema de las 8-reinas es la que se presenta a continuacin: 1. El estado inicial viene dado por una de las posibles configuraciones de las 8 Reinas sobre un tablero 8x8. 2. El operador: aadir una reina a cualquier casilla. 3. El test del objetivo se cumple cuando se alcanza el estado meta, o sea, cuando las 8 reinas estn sobre el tablero de forma que no estn amenazadas entre s. 4. El coste de cada una de las operaciones es uniforma e igual a uno. El coste del camino ser la suma de los costes de las operaciones aplicadas hasta alcanzar la solucin. 7. Heursticas

3.

Estado inicial

El principal obstculo en este problema es que no podemos definir una funcin ptima h_(n) debido a que no hay coste asociado al camino. Eso no quiere decir que no se puedan definir funciones heursticas; para la resolucin de este problema hemos utilizado las siguientes funciones heursticas: h1: Total de posiciones no amenazadas dejadas por cualquier alternativa dada. h2: Mayor diagonal, de cada uno de los posibles nuevos estados, de la ltima Reina aadida, se miden sus dos diagonales y nos quedamos con aquel estado que tenga, en su ltima reina, la mayor diagonal de cualquiera de las dos posibles. 8. Algoritmo Sea N el conjunto de vectores de k-prometedores, , sea el grafo dirigido tal que si y solo si existe un entero k, con tal que U es k-prometedor V es (k + 1)-prometedor Ui = Vi para todo Este grafo es un rbol. Su raz es el vector vaco correspondiente a k = 0. sus hojas son o bien soluciones (k = 8), o posiciones sin salida (k < 8). Las soluciones del problema de las ocho reinas se pueden obtener explorando este rbol. Sin embargo no generamos explcitamente el rbol para explorarlo despus. Los nodos se van generando y abandonando en el transcurso de la exploracin mediante un recorrido en profundidad.

Comienza con el tablero de ajedrez vaco 4. Espacio de estados

Tablero con n reinas sin atacarse 5. Costo del camino:

Cada movimiento o paso, tiene un costo de uno (1), por lo tanto el camino desde un estado inicial a un estado meta es igual al nmero de pasos (o movimientos) que se dan para alcanzar el estado meta

6.

Estado final

Es el estado al que se debe llegar para terminar el juego, con las 8 reinas en el tablero sin atacarse.

Hay que decidir si un vector es k-prometedor, sabiendo que es una extensin de un vector (k 1)-prometedor,

nicamente necesitamos comprobar la ltima reina que haya que aadir. Este se puede acelerar si asociamos a cada nodo prometedor el conjunto de columnas, el de diagonales positivas (a 45 grados) y el de diagonales negativas (a 135 grados) controlados por las reinas que ya estn puestas.

using namespace std; const int N = 8; int fac(int n) { int ret = 1; if(n <= 1) return 1; for(int i = 2 ; i <= n ; ++i) ret *= i; return ret; } bool isCorrectChecker(vector<int>& ar) { for(int i = 0 ; i < ar.size() ; ++i) { for(int j = 0 ; j < ar.size() ; ++j) if( abs(ar[i] - ar[j]) == abs(i - j) && i != j ) return false; } return true; } vector< vector<int> > getCorrectChecker(vector<int>& ar) { vector< vector<int> > ret; for(int i = 0 ; i < fac( ar.size() ) ; ++i) { next_permutation(ar.begin(), ar.end()); if( isCorrectChecker(ar) ) ret.push_back( ar ); } return ret; } void showResult(vector< vector<int> >& result) { for(int i = 0 ; i < result.size() ; ++i) { for(int j = 0 ; j < result[i].size() ; ++j) cout << result[i][j] << \" \"; cout << endl; } } vector<int> getDatas() { vector<int> ret(N); for(int i = 0 ; i < N ; ++i) ret[i] = i + 1; return ret; } int main(int argc, char* argv[]) {

procedimiento

// es k-prometedor// // // // // // // si entonces //un vector 8-prometedor es una solucin// escribir si no //explorar las extensiones (k + 1)prometedoras de sol// para hasta hacer si y y entonces // prometedor// es (k + 1)-

El algoritmo comprueba primero si k = 8, si esto es cierto resulta que tenemos ante nosotros un vector 8-prometedor, lo cual indica que cumple todas las restricciones originando una solucin. Si k es distinto de 8, el algoritmo explora las extensiones (k + 1)-prometedoras, para ello realiza un bucle, el cual va de 1 a 8, debido al nmero de reinas. En este bucle se comprueba si entran en jaque las reinas colocadas en el tablero, si no entran en jaque, se realiza una recurrencia en la cual incrementamos k (buscamos (k + 1)prometedor) y aadimos la nueva fila, columna y diagonales al conjunto de restricciones. Al realizar la recurrencia hemos aadido al vector sol una nueva reina la cual no entra en jaque con ninguna de las anteriores, adems hemos incrementado el conjunto de restricciones aadiendo una nueva fila, columna y diagonales (una positiva y otra negativa) prohibidas 8. Algoritmo codificado en c++ #include \"stdafx.h\" #include \"iostream\" #include \"vector\" #include \"cmath\" #include \"algorithm\"

int totalNum = 0; vector<int> ar = getDatas(); vector< vector<int> > result = getCorrectChecker(ar); showResult(result); return 0; } PROBLEMAS DE CRIPTOARITMETICA Las letras representan dgitos, el objetivo es determinar una sustitucin de dgitos por letras de manera que la operacin resultante sea correcta aritmticamente. Por lo general cada letra representa un dgito distinto. Estado inicial: Ninguna letra ha sido reemplazada por algn dgito. Funcin de sucesor: Reemplazar todas las veces que aparezca una letra con un dgito que no haya aparecido en el problema. Prueba de meta: Si en el problema slo hay dgitos y representan una suma correcta. Costo de la ruta: Cero. Todas las soluciones son igualmente vlidas. Solucin: SEND + MORE MONEY 1000*S+100*E+10*N+D 1000*M+100*O+10*R+E 1000*M+1000*O+100*N+10*E+Y 9567 + 1085 10652

+ 734 1468 Variables: T,W;O;F;U;R Dominios: [1:;9] para T;F [0:;9] para W,O,U,R PROBLEMAS MISIONEROS Y CANIBALES Tres misioneros y tres canbales quieren cruzar un ro. Solo hay una canoa que puede ser usada por una o dos personas, ya sean misioneros o canbales. Hay que tener cuidado en que en ningn momento el nmero de canbales supere al de misioneros en ninguna de las dos orillas, o se los comern. Estado inicial: 3M y 3C en la izquierda, 0M y 0C en la derecha, y la canoa en la izquierda. Aqu es donde empezamos. Viajes: 1M y 0C, 0M y 1C, 1M y 1C, 2M y 0C, 0M y 2C. Son las posibilidades de personal que puede ir en la canoa. Como no busco todas las soluciones, el resultado depender del orden en el que se prueben estas posibilidades. Funcin de sucesor: Aqu planteamos 2 funciones, para simplificar el algoritmo: valido?(estado): devuelve cierto si un estado es vlido. Comprueba que el nmero de individuos sea correcto, porque probamos todos los viajes, aunque sean imposibles. Adems verifica las condiciones del problema (que no se coman a la gente). canoa(estado, viaje): modifica el estado segn el viaje indicado. //devuelve si un estado es vlido para las reglas del juego Funcion valido?(estado) //logico, que no hayan de ms o de menos si (estado[Izq][M] > 3 || estado[Izq][M] < 0 || estado[Der][M] > 3 || estado[Der][M] < 0 || estado[Izq][C] > 3 || estado[Izq][C] < 0 || estado[Der][C] > 3 || estado[Der][C] < 0 ) retornar falso //que no haya mas C que M a la Izq sino si (estado[Izq][M] != 0 &&

Variables: S;E;N;D;M;O;R; Y Dominios: [1:;9] para S;M

[0:;9] para E;N;D;O;R; Y TWO + TWO FOUR 100*T+10*W+O 100*T+10*W+O 1000*F+100*O+10*U+R 734

estado[Izq][M] < estado[Izq][C] ) retornar falso // que no haya mas C que M a la Der sino (estado[Der][M] != 0 && estado[Der][M] < estado[Der][C]) retornar falso sino retornar verdadero fin_si fin_si fin_si Fin_valido // cambia el estado segn indica el viaje Funcin Canoa(estado, viaje) estado[estado[Canoa]][M] -= viaje[M] estado[estado[Canoa]][C] -= viaje[C] si (estado[Canoa] == Izq) estado[Canoa] = Der sino estado[Canoa] = Izq fin_si estado[estado[Canoa]][M] += viaje[M] estado[estado[Canoa]][C] += viaje[C] fin_funcion Realizamos un bucle que da vueltas mientras el estado no sea el que deseamos. En una primera fase vamos probando viajes hasta que uno sea vlido y adems no nos lleve a un estado anterior (para evitar bucles, que sabemos que el resultado no los tiene). Si encontramos un estado vlido, almacenamos el estado actual y tomamos en nuevo como bueno. En caso de que no se haya encontrado un estado, pues empleamos el backtracking y volvemos al estado anterior para probar otra posibilidad. Y lo presentamos en el siguiente algoritmo: si

Mientras (estado != Estado_fin) si (posibles == nulo) Escribir "NO he encontrado solucion!" Salir Fin_si // probamos viajes hasta que se nos acaben o uno sea vlido mientras (posibles!=vacio) viaje = posibles.desplazar // duplicamos los vectores internos posibleEstado = [ estado[Izq].duplicar, estado[Der].duplicar, estado[Canoa] ] canoa(posibleEstado, viaje) // salimos si es vlido y no se ha repetido break si valido?(posibleEstado) && anterior.indice(posibleEstado) == nulo // no es vlido posibleEstado = nulo Fin_mientras // tenemos uno vlido? si (posibleEstado != nulo) // nos acordamos del estado actual anterior.push estado viajes.push posibles // aceptamos el viaje como bueno (por ahora) estado = posibleEstado posibles = Viajes.duplicar sino // el viaje no nos ha llevado a un resultado // asi que recuperamos el estado anterior estado = anterior.pop posibles = viajes.pop posibleEstado = nulo fin_si fin_mientras Escribir "Tenemos una solucin!"

Prueba de meta: 0M y 0C en la izquierda, 3M y 3C en la derecha, y la canoa en la derecha. Aqu es a donde queremos llegar. M:3 M:2 M:3 M:3 M:3 M:1 M:2 M:0 M:0 M:0 M:1 M:0 Solucin: C:3 \___/ ~~~~~~~~ C:2 ~~~~~~~~ \___/ C:2 \___/ ~~~~~~~~ C:0 ~~~~~~~~ \___/ C:1 \___/ ~~~~~~~~ C:1 ~~~~~~~~ \___/ C:2 \___/ ~~~~~~~~ C:2 ~~~~~~~~ \___/ C:3 \___/ ~~~~~~~~ C:1 ~~~~~~~~ \___/ C:1 \___/ ~~~~~~~~ C:0 ~~~~~~~~ \___/

M:0 M:1 M:0 M:0 M:0 M:2 M:1 M:3 M:3 M:3 M:2 M:3

C:0 C:1 C:1 C:3 C:2 C:2 C:1 C:1 C:0 C:2 C:2 C:3

Mover2M(x, y) tranporta 2 misioneros desde x hasta y; y as sucesivamente. Las precondiciones de cada operador se dividen en tres grupos de requisitos. El primer grupo (primera columna de precondiciones) hace referencia a que para transportar a una persona desde x, esa persona debe estar en x. As, el operador Mover1M1C(x, y) requiere que en x haya al menos un canbal y un misionero. El segundo grupo de condiciones (segunda columna) hace referencia a la poscion de la barca: para todos los operadores, la barca debe estar en la posicion de origen. El tercer grupo de condiciones evita que los canbales se coman a los misioneros, evitando hacer movimientos que dejen a mas canbales que misioneros en cualquier orilla.

Cuadro 1: Operadores del problema de los canbales y los misioneros En la tabla tambien se incluyen los efectos del operador, que suele incluir el cambio en la posicion de la barca, as como el cambio en el numero de canbales y misioneros en cada orilla.

Ejercicio 1
En la orilla de un ro hay 3 misioneros y 3 canbales y todos ellos pretenden cruzar al otro lado. La barca que se utiliza para cruzarlo solo tiene capacidad para dos personas, con lo que alguien ha de estar volviendo siempre a la orilla inicial mientras quede gente sin cruzar. Ademas, si en alguna ocasion y en cualquiera de las orillas se encuentran un numero mayor de canbales que de misioneros, los primeros se comeran a los segundos. 1. Como representaras los estados? 2. Cuales seran los operadores? 3. Que heursticas existen para este problema?Son admisibles?

Heursticas
En este caso, vamos a obtener las heursticas por relajacion del problema original. Para dicha relajacion, partimos de las precondiciones expuestas en la Tabla 1. Estas precondiciones se pueden relajar facilmente teniendo en cuenta los tres tipos de precondiciones definidas anteriormente: 1. Eliminar primer grupo de precondiciones. Si eliminamos ese primer grupo de condiciones, se obtiene un problema relajado que no parece ser mucho mas facil de resolver que el problema original, por lo que no tiene mucho sentido. 2. Eliminar segundo grupo de precondiciones. Al eliminar el segundo grupo de condiciones, el problema resultante es mas facil que el original, puesto que se puede asumir que hay infinitas barcas tanto en un lado como en otro. Este problema tiene una solucion muy sencilla, que es asumir que siempre viajan un canbal y un misionero juntos, con el operador Mover1M1C(i, f). Por tanto, la heurstica resultante de este problema relajado es: h1(n) = Ci +Mi 2 (1) asumiendo que en el estado n se cumplen los requisitos definidos por el grupo de precondiciones 3. 3. Al eliminar el tercer grupo de condiciones, obtenemos un problema relajado en el que los canbales nunca se comen a los misioneros. Entonces, en cada viaje de ida y vuelta, podemos transportar a una persona (dado que la otra tendra que volver para llevar la barca). Por tanto, la heurstica resultante es: h2(n) = 2 (Ci +Mi) orilla(n) (2) donde orilla(n) = 1 si en el estado n la barca esta en la orilla i (B = i), y orilla(n) = 0 si la barca esta en la orilla final (B = f). Una cuarta posibilidad sera eliminar el grupo de condiciones 2 y 3 a la vez. Sin embargo, como hemos visto anteriormente, este problema es equivalente a eliminar solo el grupo de condiciones 2. Las dos heursticas son admisibles, puesto que son resultado de relajar el problema original. Para decidir que heurstica elegir, h2 o h3, estudiamos cual es la mas informada, puesto que sera la que, siendo admisible,

Solucion Ejercicio 1
Estados
Se podra indicar la posicion de la barca, junto con el numero de misioneros y canbales que hay en cada lado. Se podra pensar que, dado que el numero de personas en el extremo final puede calcularse a partir de los que hay en el inicial, basta con indicar la posicion de la barca y los misioneros y canbales que quedan en el extremo inicial. Sin embargo, la primera aproximacion permite describir mas facilmente las precondiciones y efectos de los operadores, por lo que mantenemos la representacion inicial. Ademas, el espacio de estados tiene el mismo tamano e identica semantica con ambas representaciones. Formalmente, por tanto, un estado es una terna (Mi,Ci,B,Mf ,Cf ) en la que: B [i, f] indica la posicion de la barca, por lo que toma el valor i si esta en el extremo inicial, o f si esta en el final Mi,Ci,Mf ,Cf [0, . . . , 3] indican el numero de misioneros y canbales que quedan en el extremo inicial y final del ro, respectivamente De esta manera, el estado inicial se representa como (3, 3, i, 0, 0) y el final como (0, 0, f, 3, 3)

Operadores
El conjunto de operadores es el mostrado en al Tabla 1. Se dispone de 5 operadores. Cada uno de ellos consiste en transportar personas de la orilla x a la orilla y: Mover1C(x, y) transporta 1 canbal desde la orilla x hasta la orilla y;

tendra un valor mas cercano a h_. Se observa facilmente que la mas informada es h2, puesto que h2(n) h3(n), sea cual sea el valor de Ci y de Mi para el estado n. Por tanto, elegimos h2(n)

Ejercicio 2
Las torres de Hanoi es un juego matematico ideado en el siglo XVIII. Este juego consiste en pasar 64 discos de diametro decreciente, de un poste a otro poste, utilizando un tercer poste auxiliar para los pasos intermedios, tal y como muestra la Figura 1.

Cada vez solo se puede mover un disco, los discos siempre deben estar en algun poste y no se puede colocar un disco sobre otro de menor tamano. 1. Como representaras los estados? 2. Cuales seran los operadores? 3. Que heursticas existen para este problema?Son admisibles?

Solucion Ejercicio 2
Estados
Un estado puede representarse como una lista con los discos que hay en cada uno de los postes. En caso de tres postes, tenemos una lista con tres sublistas. Cada disco viene representado con un identificador que indica ademas su diametro. Estado: (P1, P2, P3), donde Pi(i = 1, 2, 3) es una lista de valores entre 1 y 64 Estado inicial: ((64, 63, 62, . . . , 5,4,3,2,1) ()()) Estado final: (()()(64, 63, 62, ?, 5,4,3,2,1)) Existe un unico operador,Mover(Pi, Pj) que mueve un disco del poste Pi al poste Pj , por lo que i, j [1, 2, 3], i 6= j. Las precondiciones del operador son: 1. Pi 6= [] 2. (Pj = []) ( para Pi = [x|Li], Pj = [y|Lj ], x y) Donde Li y Lj contienen la lista de discos que hay en Pi y Pj respectivamente, pero eliminando el primer disco. Los efectos del operador Mover(Pi, Pj), donde Pi = [x|Li], Pj = [y|Lj ], son: Pi = [Li] Pj = [x|y|Lj ]

h1(n) = 2 kP1k + 2 kP2k 1 h(n) = 2 (kP1k + kP2k) 1 (3) donde el estado n es (P1P2Pi), kP1k es el numero de elementos en el poste P1, y kP2k es el numero de elementos en el poste P2. Para ser exactos, a la heurstica anterior habra que restarle 1 por cada poste en el que haya discos (es decir, si los dos postes tienen discos, se le resta 2, y si solo uno de ellos tiene discos, se le resta 1). Si no se tiene en cuenta este detalle, la heurstica se puede simplificar a h2(n) = (kP1k + kP2k). Sin embargo, esta heurstica solo es valida si asumimos que los discos colocados en el poste final estan, en verdad, bien colocados (desde el de mayor tamano, al de menor, con diferencias de 1 en el diametro de cada disco colocado). En caso contrario, la heurstica debera penalizar tambien los discos colocados en el tercer poste, haciendo que: h3(n) = 2 (kP1k + kP2k + kP3k) 1 (4) Aun as, el valor de esta heurstica todava no corresponde con el valor real del coste optimo del problema relajado. Sin embargo, todas las heursticas descritas estan menos informadas que la del problema relajado, y subestiman el coste. Por tanto, son tambien admisibles, aunque menos informadas. Otra posible relajacion de este problema es la resultante de eliminar la restriccion de que solo hay tres postes. Es decir, podemos asumir que hay tantos postes intermedios como sean necesarios. Con esta relajacion obtenemos la misma heurstica definida anteriormente.

Heuristica
Para generar una heurstica, obtenemos un problema relajado a partir del original, simplemente eliminando alguna precondicion del operador Mover. En este caso, no tiene sentido eliminar la precondicion 1, puesto que eso anadira mas discos a nuestro problema, as que eliminamos solo la precondicion 2. Al eliminar esta segunda precondicion, resolver el problema es muy sencillo. Por ejemplo, si se supone la situacion inicial, en la que todos los discos estan en el primer poste, solo hay que ir moviendo todos los discos uno a uno al poste intermedio, y de ah nuevamente uno a uno al definitivo. Esto produce dos movimientos por cada disco que no este colocado correctamente en el poste adecuado, excepto para el ultimo (que puede ir directamente al poste final sin pasar por el intermedio). Para otros estados distinto al inicial, esta forma de resolver el problema es, al menos, una cota inferior, asegurando que la heurstica es admisible para todos los estados del problema origina. Esto nos genera la siguiente heurstica:

Anda mungkin juga menyukai