Вы находитесь на странице: 1из 21

8puzzle.

h #define #define #define #define #define UP 0 DOWN 1 RIGHT 2 LEFT 3 NUM_OPERATORS 4

typedef struct tState_ { int cells[3][3]; int r,c; } tState

8puzzle.c
#include <stdio.h> #include "8puzzle.h" #include "search.h" static int initcells[3][3] = { {1,2,3}, {4,5,6}, {7,8,0} }; static int goalcells[3][3] = { {4,1,3}, {7,2,5}, {0,8,6} }; /* static int goalcells[3][3] = { {1,2,3}, {4,0,6}, {7,5,8} }; */ tState *initialState() { tState *s = (tState *)malloc(sizeof(tState)); int i,j; for (i=0;i<3;i++) for (j=0;j<3;j++) s->cells[i][j]=initcells[i][j]; s->r=2; s->c=2; return s; } int goalTest(tState *s) {

int i,j; for (i=0;i<3;i++) for (j=0;j<3;j++) if (s->cells[i][j]!=goalcells[i][j]) return 0; return 1; } int executable(unsigned op,tState *s) { switch(op) { case UP: return s->r>0; case DOWN: return s->r<2; case LEFT: return s->c>0; case RIGHT: return s->c<2; } } tState *successorState(unsigned op,tState *old) { tState *result = (tState *)malloc(sizeof(tState)); /* Copy result from old */ memcpy(result,old,sizeof(tState)); switch(op) { case UP: result->r--; break; case DOWN: result->r++; break; case LEFT: result->c--; break; case RIGHT: result->c++; break; } result->cells[result->r][result->c]=0; result->cells[old->r][old->c]=old->cells[result->r][result->c]; return result; } int cost(unsigned op,tState *s) { return 1; } int stateEqual(tState *s1,tState *s2) { return (memcmp(s1,s2,sizeof(tState))==0); } /*--- DISPLAY FUNCTIONS -----------------------------------------------*/ void showState(tState *s) { int i,j; for (i=0; i<3; i++) { for (j=0; j<3; j++) printf("%d ",s->cells[i][j]); printf("\n"); } } void showOperator(unsigned op) { switch(op) { case UP: printf("UP");break;

case DOWN: printf("DOWN");break; case LEFT: printf("LEFT");break; case RIGHT: printf("RIGHT");break; } }

////////////queue.h
/************************************************************************ ***** * QUEUE.h * Pedro Cabalar 15/10/2004 * * A QUEUE is a single connected round list. The QUEUE itself is a pointer * used to point at any moment the last element in the list. ************************************************************************* ****/ struct qNode { struct qNode *next; int data[0]; }; typedef struct qNode *QUEUE; /* qEMPTY: returns the empty queue (represented as the NULL pointer) */ #define qEMPTY NULL /* qIsEmpty(QUEUE q); * Decides whether QUEUE q is empty or not. It is equivalent to * the expression q==qEMPTY */ #define qIsEmpty(q) ((q)==NULL) /* qIsNotEmpty(QUEUE q); * The opposite to qIsEMPTY. It is equivalent to the expression q!=qEMPTY */ #define qIsNotEmpty(q) ((q)!=NULL) /* qFirst(QUEUE q,type); * Returns a pointer to the data of the first element in the list, assuming * that the element type is 'type'. * EXAMPLE: * printf("%d\n",*qFirst(q,int)); * will print the first element of q, assuming it is an integer number. * REQUIRES: q must be non-empty.

*/ #define qFirst(q,type) ((type *)(q)->next->data) /* qNext(QUEUE q,type); * Returns a QUEUE pointer to the next element from q. * Remember that the end of the list is not a NULL pointer, but is connected * instead to the first element (it is a round list). * REQUIRES: q must be non-empty. */ #define qNext(q) ((q)->next) /* qInsertAt(QUEUE *pq,QUEUE pos,void *e,unsigned int size); * Inserts an element of size 'size' whose address is pointer 'e' at the * position pointed by QUEUE pointer 'pos'. * REQUIRES: 'pos' must be one of the pointers inside the queue *pq. * MODIFIES: the queue elements and (possibly) the queue pointer *pq. */ #define qInsertAt(pq,pos,e,size) ((*pq)==(pos))?qInsertFirst(pq,e,size):qInsertFirst(&p,e,size) /* qPUSH(QUEUE *pq,void *e,type) * Pushes element of type 'type' whose address * top of the queue pointed by 'pq'. Note that (QUEUE *), * since the queue pointer can be modified. * MODIFIES: the queue elements and (possibly) */ #define qPUSH(pq,e,type) qInsertFirst(pq,(void is pointer 'e' at the 'pq' must be of type the queue pointer *pq. *)e,sizeof(type))

/* qPOP(QUEUE *pq,void *e,type) * Retrieves and deletes the top element of queue *pq, storing it at address * 'e', assuming that its type is 'type'. * REQUIRES: the queue *pq must be non-empty. * MODIFIES: the content of the area pointed by 'e', the queue elements, and * (possibly) the queue pointer *pq. */ #define qPOP(pq,e,type) {memcpy((void *)e,(*(pq))->next>data,sizeof(type)); qDeleteFirst(pq);} /* See qOrderedInsert */ #define REPEATING 1 int qInsertFirst(QUEUE *pq, void *e, int size); /* Inserts an element of size 'size' pointed by 'e' as the first element of * queue *pq. * MODIFIES: the queue elements and (possibly) the queue pointer *pq. */ int qInsertLast(QUEUE *pq, void *e, int size); /* Inserts an element of size 'size' pointed by 'e' as the last element of * queue *pq. * MODIFIES: the queue elements and (possibly) the queue pointer *pq.

*/ int qDeleteFirst(QUEUE *pq); /* Deletes the first element of queue *pq * MODIFIES: the queue elements and the queue pointer *pq. */ QUEUE qBrowse(QUEUE q, int (*found)(QUEUE , void *),void *data); /* Allows browsing the queue q and performing some arbitrary operation until * the end of the queue is reached or some element is found. * Argument 'found' is a pointer to a function of type * int (*found) (QUEUE pos,void *data) * that will be called for each pointer 'pos' to each element in list 'q'. * When this function returns 0, the browsing will continue until reaching * the queue end. Otherwise, it may return 1 (for instance, when some searched * element is found) and the browsing will stop at that moment. * The pointer 'data' is used to pass common data to each call of function * (*found). * REQUIRES: function (*found) should return 0 or 1 and should not modify * the element pointers (should not delete or insert elements in q). * MODIFIES: It depends on function (*found), which can modify the content of * the elements in the queue. * EXAMPLE: We want to add some constant k to all the elements in a list of * integer numbers until we reach some negative number: * * int addConstant(QUEUE q,void *data) { * if (*qFirst(q,int) < 0) * return 1; * int *pk=(int *)data; * *qFirst(q,int) += *pk; * return 0; * } * * ... * int k=10; * qBrowse(q,addConstant,&k); * ... */ int qDelete(QUEUE *pq, QUEUE pos); /* Deletes the element of queue *pq at position pointed by queue pointer 'pos'. * REQUIRES: 'pos' must be one of the valid position pointers inside queue * *pq. * MODIFIES: the queue elements and possibly the content of *pq. */ int qMove(QUEUE *q1, QUEUE *q2, int (*movethis)(void *),int size); /* Moves all the elements in *q1 to *q2 that satisfy a property specified

* by the generic function (*movethis). The moved elements are removed from * *q1 and appended to *q2, that is, they are inserted in the end. The elements * size is fixed to 'size'. * MODIFIES: the elements of both queues, and possibly *q1 and *q2. */ int qFree(QUEUE *q); /* Deletes all the queue elements leaving *q empty. */ int qOrderedInsert(QUEUE *q, void *e, int size,int (*cmp)(void *, void *), char repeating); /* Makes an ordered insertion of element of size 'size' pointed by 'e' in * queue *q. Generic function (*cmp) is used to compare two elements * (passed as void pointers) so that it returns a value <0 if the first * one is lower, =0 if they are equal, or >0 if the first element is greater. * Argument 'repeating' is used to point out whether we allow repeated elements * or not (1 means with repeated elements, 0 means no repeated elements). * REQUIRES: the elements in *q should be ordered with respect to (*cmp) * ordering criterion. * MODIFIES: the queue elements and (possibly) the pointer *q. */ int qDeleteThoseThat(QUEUE *q,int (*DeleteThis)(QUEUE pos,void *data),void *data); /* Deletes from queue *q all those elements that satisfy proerty specified * by generic function (*DeleteThis). Argument 'data' is used for passing * additional data to (*DeleteThis) if needed. * REQUIRES: function DeleteThis should return 1 if the first element of * pointer 'pos' should be deleted, and 0 otherwise. * MODIFIES: the queue elements and (possibly) the pointer *q. */ QUEUE qCopy(QUEUE q,int size); /* Returns a full copy of q. */ QUEUE qMerge(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *),char repeating); /* It returns a list containing the result of merging the two ordered lists q * and r. The new list contains a copy of the elements in the old lists. * The ordering criterion is specified by the generic function (*cmp) (see * qOrderedInsert). When 'repeating' is 0, repeated elements are copied only * once. The size elements is fixed to 'size'. */ QUEUE qIntersect(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *)); /* Returns the common elements of queues q and r. The new list contains a * copy of the elements in the old lists. Generic function (*cmp) returns 0

* when two elements are equal (see qOrderedInsert). The size elements is * fixed to 'size'. */ QUEUE qDiff(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *)); /* Returns the elements in q not in r. The new list contains a * copy of the elements in the old lists. Generic function (*cmp) returns 0 * when two elements are equal (see qOrderedInsert). The size elements is * fixed to 'size'. */ unsigned int qCount(QUEUE q); /* Returns the number of elements in a list. */ void *Queue2Array(QUEUE q,unsigned int size,unsigned int *num); /* Returns an array (void *) containing a copy of all the elements in the * queue q. The elements size is fixed to 'size'. * It also returns the number of elements in *num. */ QUEUE qCat(QUEUE q,QUEUE r); /* Returns the result of appending queue r in the end of queue q. * The new list contains a copy of the elements in the old lists. */

////////////////queue.c

#include #include #include #include

<stdio.h> <stdlib.h> <string.h> "queue.h"

#define BREAKLINK(Q,QOLD,QNEXTOLD) {(QOLD)=(Q); (QNEXTOLD)=(Q)>next;(Q)=(Q)->next; (QOLD)->next=qEMPTY;} /* Round queues */ static QUEUE qAux; int qInsertFirst(QUEUE *q, void *e, int size) { QUEUE p; if ((p=(QUEUE)malloc(sizeof(struct qNode)+size))!=NULL) { memcpy((void *)(p->data),e,size); if (qIsEmpty(*q))

{ *q=p; (*q)->next=(*q); } else { p->next = (*q)->next; (*q)->next = p; } return 1; } else return 0; } int qDeleteFirst(QUEUE *q) { QUEUE p; if (qIsEmpty(*q)) return 0; if (*q == (*q)->next) { free(*q); *q=qEMPTY; } else { p=(*q)->next; (*q)->next=p->next; free(p); } return 1; } int qInsertLast(QUEUE *q, void *e, int size) { QUEUE p; if (!qInsertFirst(q,e,size)) return 0; *q=(*q)->next; return 1; } QUEUE qBrowse(QUEUE q, int (*found)(QUEUE, void *),void *data) { QUEUE p; int stop; if (qIsNotEmpty(q)) { p=q; while (! (stop=(*found)(p,data) ) && (p=p->next)!=q ); if (stop) return p; } return NULL; }

int qDelete(QUEUE *q, QUEUE pos) { if (qIsEmpty(*q) || qIsEmpty(pos) ) return 0; if (pos->next==*q) { *q=pos; return qDeleteFirst(q); } return qDeleteFirst(&pos); } int qMove(QUEUE *q1, QUEUE *q2, int (*movethis)(void *elem),int size) { QUEUE p; p=qEMPTY; while (qIsNotEmpty(*q1)) { if ((*movethis)((void *)(*q1)->next->data)) { if (!qInsertLast(q2,(void *)((*q1)->next->data),size)) return 0; } else { if (!qInsertLast(&p,(void *)((*q1)->next->data),size)) return 0; } if (!qDeleteFirst(q1)) return 0; } *q1=p; return 1; } int qFree(QUEUE *q) { while ((*q)!=NULL) qDeleteFirst(q); } struct cmpData { void *elem; int (*cmp)(void *, void *); }; static int FirstIsgeqThan(QUEUE q,void *e) { struct cmpData *d; d=(struct cmpData*)e; return (d->cmp(q->next->data,d->elem)>=0); } int qOrderedInsert(QUEUE *q, void *e, int size,int (*cmp)(void *, void *), char repeating) { QUEUE p;

struct cmpData d; d.cmp=cmp; d.elem=e; p=qBrowse(*q,FirstIsgeqThan,&d); if (p==NULL) qInsertLast(q,e,size); else { if (!repeating && cmp(p->next->data,e)==0) return 0; qInsertAt(q,p,e,size); } return 1; } int qDeleteThoseThat(QUEUE *q,int (*DeleteThis)(QUEUE,void *),void *data) { QUEUE p; char InFirst; int n=0; if (qIsNotEmpty(*q)) { p=*q; InFirst=1; do { if (DeleteThis(p,data)) { qDelete(q,p); n++; if (InFirst) InFirst=(p==*q); } else { p=p->next; InFirst=0; } } while(qIsNotEmpty(*q) && (p!=*q || InFirst)); } return n; } static int CopyElem(QUEUE q,void *e) { qInsertLast(&qAux,q->next->data,*(int *)e); return 0; } QUEUE qCopy(QUEUE q,int size) { qAux=qEMPTY; qBrowse(q,CopyElem,&size); return qAux; }

#define COPY(Q) qInsertLast(&qAux,(Q)->data,size) #define MOVE(Q) (Q)=(Q)->next; QUEUE qMerge(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *),char repeating) { QUEUE qOld,rOld,qNextOld,rNextOld; int comp; if (qIsEmpty(q)) if (qIsEmpty(r)) return qEMPTY; else return qCopy(r,size); if (qIsEmpty(r)) return qCopy(q,size); /* Momentaneously break the round links */ BREAKLINK(q,qOld,qNextOld); BREAKLINK(r,rOld,rNextOld); qAux=qEMPTY; while (q!=qEMPTY && r!=qEMPTY) { comp=cmp(q->data,r->data); if (comp<0) {COPY(q); MOVE(q);} else if (comp>0) {COPY(r); MOVE(r);} else { COPY(q); if (repeating) COPY(r); MOVE(q); MOVE(r); } } while (q!=qEMPTY) {COPY(q); MOVE(q);} while (r!=qEMPTY) {COPY(r); MOVE(r);} /* Restore round links */ qOld->next=qNextOld; rOld->next=rNextOld; return qAux; } QUEUE qIntersect(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *)) { QUEUE qOld,rOld,qNextOld,rNextOld; int comp; if (qIsEmpty(q)||qIsEmpty(r)) return qEMPTY; /* Momentaneously break the round links */ BREAKLINK(q,qOld,qNextOld); BREAKLINK(r,rOld,rNextOld); qAux=qEMPTY; while (q!=qEMPTY && r!=qEMPTY)

{ comp=cmp(q->data,r->data); if (comp<0) {MOVE(q);} else if(comp>0) {MOVE(r);} else {COPY(q); MOVE(q); MOVE(r);} } /* Restore round links */ qOld->next=qNextOld; rOld->next=rNextOld; return qAux; } QUEUE qDiff(QUEUE q,QUEUE r,int size,int (*cmp)(void *,void *)) { QUEUE qOld,rOld,qNextOld,rNextOld; int comp; if (qIsEmpty(q)) return qEMPTY; if (qIsEmpty(r)) return qCopy(q,size); /* Momentaneously break the round links */ BREAKLINK(q,qOld,qNextOld); BREAKLINK(r,rOld,rNextOld); qAux=qEMPTY; while (q!=qEMPTY && r!=qEMPTY) { comp=cmp(q->data,r->data); if (comp<0) {COPY(q); MOVE(q);} else if(comp>0) {MOVE(r);} else {MOVE(q); MOVE(r);} } while (q!=qEMPTY) {COPY(q); MOVE(q);} /* Restore round links */ qOld->next=qNextOld; rOld->next=rNextOld; return qAux; } static int CountElem(QUEUE q,void *e) { *(unsigned int *)e+=1; return 0; } unsigned int qCount(QUEUE q) { unsigned int c=0; qBrowse(q,CountElem,(void*)&c); return c;

struct CopyArrayData { char *p; size_t size; }; static int Copy2Array(QUEUE q,void *e) { struct CopyArrayData *d; d=(struct CopyArrayData *)e; memcpy(d->p,qFirst(q,char),d->size); d->p+=d->size; return 0; } void *Queue2Array(QUEUE q,size_t size,unsigned int *num) { void *a; struct CopyArrayData d; *num=qCount(q); if (qIsEmpty(q)) return NULL; a=(void *)malloc(*num*size); d.p=(char *)a; d.size=size; qBrowse(q,Copy2Array,(void *)&d); return a; } QUEUE qCat(QUEUE q,QUEUE r) { QUEUE aux; if (qIsEmpty(q)) return r; if (qIsEmpty(r)) return q; aux=r->next; r->next=q->next; q->next=aux; return r; }

/////////////////////// hash.h
#include <stdio.h> typedef struct tHashTable_ { QUEUE *lists; /* Array of lists */ unsigned int numLists; /* Number of lists (use a prime number) */ unsigned int keySize; /* Fixed size for all keys */ } tHashTable;

typedef struct tHashEntry_ { void *key; /* Pointer to key */ void *data; /* Pointer to data */ } tHashEntry; /*---------------------------------------------------------------Creates a hash table 'numLists' lists (use a prime number), and 'keySize' fixed size for all keys REQUIRES 'numLists' should be a prime number. RETURNS the pointer to the hash table structure. */ tHashTable *hashCreate(unsigned int numLists,unsigned int keySize); /*---------------------------------------------------------------Inserts an element in the hash table. For computing the hash value, it will use h->keySize bytes beginning at the 'key' pointer. The 'data' will be stored just as a pointer. If 'data' is not used, fix it to NULL. REQUIRES pointer 'h' must point to a correctly created non-null hash structure. RETURNS 1 if the element is inserted, 0 if the key was already in the table. */ int hashInsert(tHashTable *h,void *key, void *data); /*---------------------------------------------------------------Searchs for entry 'e'. REQUIRES e->key should contain the searched key. The value of e->data before calling is irrelevant. RETURNS 0 if key was not found. 1 if key was found. If found, the corresponding data pointer is stored in e>data. */ int hashFind(tHashTable *h,tHashEntry *e); /*---------------------------------------------------------------Frees memory assigned to the hash table. It will NOT free the assigned memory to each element key and element data, just the structures that exclusively correspond to the hash table structure. */ void hashFree(tHashTable *h);

//////////////hash.c

#include "queue.h" #include "hash.h" /*---------------------------------------------------------------Creates a hash table 'numLists' lists (use a prime number), and 'keySize' fixed size for all keys REQUIRES 'numLists' should be a prime number. RETURNS the pointer to the hash table structure. */ tHashTable *hashCreate(unsigned int numLists,unsigned int keySize) { tHashTable *h=(tHashTable *) malloc(sizeof(tHashTable)); h->lists=(QUEUE *)calloc(numLists,sizeof(QUEUE)); h->numLists=numLists; h->keySize=keySize; return h; } /* Compares two hash entries using their keys. The key size is momentarily stored in the static var 'auxKeySize'. */ static unsigned int auxKeySize; static int entryCmp(void *e1, void *e2) { return memcmp(((tHashEntry *)e1)->key,((tHashEntry *)e2)>key,auxKeySize); } /* Computes the hash value for a given key */ static unsigned int hv(tHashTable *h,void *key) { int n=sizeof(unsigned int); union { unsigned int x; char p[n]; } u; unsigned int sum=0; int i; char *q=key; for (i=0;i<h->keySize/n;i++,q+=n) { memcpy(u.p,q,n); sum+=u.x; } for (i=0;i<n;i++) u.p[i]=0; memcpy(u.p,q,h->keySize % n); sum += u.x; return sum % h->numLists; } /*---------------------------------------------------------------Inserts an element in the hash table. For computing the hash value,

it will use h->keySize bytes beginning at the 'key' pointer. The 'data' will be stored just as a pointer. If 'data' is not used, fix it to NULL. REQUIRES pointer 'h' must point to a correctly created non-null hash structure. RETURNS 1 if the element is inserted, 0 if the key was already in the table. */ int hashInsert(tHashTable *h,void *key, void *data) { tHashEntry e; e.key=key; e.data=data; auxKeySize=h->keySize; return qOrderedInsert(&h>lists[hv(h,key)],&e,sizeof(tHashEntry),entryCmp,0); } /* Searchs the first entry which is greater or equal than e */ static int geqEntry(QUEUE q, void *e) { return entryCmp(qFirst(q,tHashEntry),e)>=0; } /*---------------------------------------------------------------Searchs for entry 'e'. REQUIRES e->key should contain the searched key. The value of e->data before calling is irrelevant. RETURNS 0 if key was not found. 1 if key was found. If found, the corresponding data pointer is stored in e>data. */ int hashFind(tHashTable *h,tHashEntry *e) { QUEUE aux; /* Ordered search in the corresponding list */ auxKeySize=h->keySize; aux=qBrowse(h->lists[hv(h,e->key)],geqEntry,e); if (aux!=qEMPTY && entryCmp(qFirst(aux,tHashEntry),e)==0) { e->data=qFirst(aux,tHashEntry)->data; return 1; } return 0; /* not found */ } /*---------------------------------------------------------------Frees memory assigned to the hash table. It will NOT free the assigned memory to each element key and element data, just the structures that exclusively correspond to the hash table structure. */ void hashFree(tHashTable *h) { /* Delete all lists */ int i; for (i=0;i<h->numLists;i++)

while (qIsNotEmpty(h->lists[i])) qDeleteFirst(&h->lists[i]); free(h->lists); /* Free the lists array */ free(h); /* Free the hash table structure */ }

///////////////search.c
#include #include #include #include #include #include #include #include <stdio.h> <unistd.h> "queue.h" "hash.h" "domain.h" "search.h" <sys/time.h> <sys/resource.h>

struct { enum {BREADTH,DEPTH} fringeInsertion; int (*algorithm)(); char verbose; } options; struct { unsigned int expandedNodes; struct rusage resources; } statistics; int inPath(tSearchNode *node,tState *s) { while (node!=NULL) { if (stateEqual(node->state,s)) return 1; node=node->parent; } return 0; } QUEUE expand(tSearchNode *node) { QUEUE successors=qEMPTY; unsigned op; for (op=0;op<NUM_OPERATORS;op++) if (executable(op,node->state)) { tSearchNode *new; tState *s=successorState(op,node->state); if (options.fringeInsertion==DEPTH && inPath(node->parent,s)) free(s); else { new=(tSearchNode *)malloc(sizeof(tSearchNode)); new->state=s; new->parent=node;

new->action=op; new->pathCost=node->pathCost + cost(op,node->state); new->depth=node->depth+1; qInsertLast(&successors,&new,sizeof(tSearchNode *)); } } statistics.expandedNodes++; return successors; }

void printReversePath(tSearchNode *node) { if (node->parent==NULL) return; printReversePath(node->parent); showOperator(node->action); if (options.verbose) { printf("\n"); showState(node->state); printf("\n"); } else printf("; "); }

void printSolution(tSearchNode *node) { printf("Solution: \n"); printReversePath(node); printf("\nDepth=%d\n",node->depth); printf("Cost=%d\n",node->pathCost); } void insertNode(QUEUE *fringe,tSearchNode **n) { switch(options.fringeInsertion) { case BREADTH: qInsertLast(fringe,n,sizeof(tSearchNode *)); break; case DEPTH: qInsertFirst(fringe,n,sizeof(tSearchNode *)); break; } } tSearchNode *rootNode() { /* Create the root node */ tSearchNode *root=(tSearchNode *)malloc(sizeof(tSearchNode)); root->state=initialState(); root->parent=NULL; root->pathCost=0; root->depth=0; return root; } int treeSearch() { tSearchNode *node,*n,*root=rootNode();

QUEUE fringe=qEMPTY,successors; qInsertFirst(&fringe,&root,sizeof(tSearchNode *)); while (1) { if (qIsEmpty(fringe)) return 0; qPOP(&fringe,&node,sizeof(tSearchNode *)); if (goalTest(node->state)) {printSolution(node); return 1;} successors = expand(node); while (!qIsEmpty(successors)) { qPOP(&successors,&n,sizeof(tSearchNode *)); insertNode(&fringe,&n); } } } int graphSearch() { tSearchNode *node,*n,*root=rootNode(); QUEUE fringe=qEMPTY,successors; tHashTable *closed=hashCreate(10007,sizeof(tState)); tHashEntry e; qInsertFirst(&fringe,&root,sizeof(tSearchNode *)); while (1) { if (qIsEmpty(fringe)) return 0; qPOP(&fringe,&node,sizeof(tSearchNode *)); if (goalTest(node->state)) {printSolution(node); return 1;} e.key=node->state; if (hashFind(closed,&e)) { free(node->state); free(node); continue; } /* already visited state */

hashInsert(closed,node->state,NULL); successors = expand(node); while (!qIsEmpty(successors)) { qPOP(&successors,&n,sizeof(tSearchNode *)); insertNode(&fringe,&n); } } } extern char *optarg; extern int optind; int main (int argc,char *argv[]) { /* Processing options */ int c;

options.algorithm=treeSearch; options.fringeInsertion=BREADTH; options.verbose=0; statistics.expandedNodes=0; while ((c = getopt(argc, argv, "a:f:v")) != EOF) { switch (c) { case 'a': if (!strcmp(optarg,"tree")) options.algorithm=treeSearch; else { if (!strcmp(optarg,"graph")) options.algorithm=graphSearch; else { printf("Unrecognized algorithm %s.\n",optarg); exit(1); } } break; case 'f': if (!strcmp(optarg,"breadth")) options.fringeInsertion=BREADTH; else { if (!strcmp(optarg,"depth")) options.fringeInsertion=DEPTH; else { printf("Unrecognized type of fringe insertion %s.\n",optarg); exit(1); } } break; case 'v': options.verbose=1;break; case 'h': case '?': printf("search -a <algorith_mname> -f <fringe_insertion>"); } } if (!(options.algorithm())) printf("No solution.\n"); printf("%d expanded nodes.\n",statistics.expandedNodes); getrusage(RUSAGE_SELF,&statistics.resources); printf("%ld.%03ld seconds.\n", statistics.resources.ru_utime.tv_sec, statistics.resources.ru_utime.tv_usec/1000); }

////////////////search.h
tState *initialState(); int goalTest(tState *s); int executable(unsigned op,tState *s); tState *successorState(unsigned op,tState *s); int cost(unsigned op,tState *s);

void showOperator(unsigned op); void showState(tState *s);

/////////////////////////////////////////////////////////////////////////////////NOSE PARA QUE ES


SOURCES=queue.c domain.c search.c hash.c INCLUDES=$(SRCS:%.c=%.h) search : $(INCLUDES) $(SOURCES) gcc -o search $(SOURCES) debug : $(INCLUDES) $(SOURCES) gcc -ggdb -o search $(SOURCES) domain : rm -f ln -s ln -s touch clean : rm -f search *.o domain.c domain.h $(DOM).c domain.c $(DOM).h domain.h domain.c

Вам также может понравиться