Arama Algoritmaları
Arama Algoritmaları
Bu yazıda çeşitli Arama Algoritmalarının C kodlarına yer verim.
Yer Alan algoritmalar:
•Breadth First Search (BFS)
•Depth First Search (DFS)
•Depth limited Search (DLS)
•Iterative Deepening Search (IDS)
•Bidirectional Search (BS)
Yukarıda yer alan algoıritmalaları tek bir kaynak kodda toparladım.
[sourcecode language=”plain”]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//////////////// our tree /////////////////
struct tree{
int index;
int board[9];
int depth;
int fringe_size;
struct tree *father;
struct tree *children[4];
struct tree *next;
struct tree *back;
};
typedef struct tree T;
//////////////// our Fringe ///////////////////////
typedef struct tree F;
typedef F *Fptr;
Fptr head=NULL,tail=NULL;
Fptr Ghead=NULL,Gtail=NULL;
//////////////// define our goal state ///////////////
int goal_state[9]={1 ,2, 3, 8, 0 , 4 , 7 , 6 , 5 };
int counter;
int limit=0;
int i , j , k;
int inx=1; // index of our state
T *root=NULL; // ROOT of our tree
int swap=0; // use in to solve Bidirectional Search
int check_BS=0; // use in to solve Bidirectional Search
//////////////// General Prototypes /////////////////
T *randomState();
void printstate(T *);
int checkGoal(T *);
int checkGoal_BS(T *B ,T *G);
int checkRepeated(T *node);
void startSolve_BFS(T *B);
void startSolve_DFS(T *B);
void startSolve_DL(T *B);
void startSolve_IDS(T *B);
void startSolve_BS(T *B ,T *G);
//////////////// Tree Prototypes ////////////////////
T *createNode();
void expand(T *old,int dir);
//////////////// Fringe Prototypes //////////////////
void printFringe(Fptr);
int emptyF(Fptr);
int popF(Fptr *,Fptr *);
void pushF(Fptr *, Fptr *, T *);
int Fringe_size(Fptr);
FILE *fp;
//////////////// File Prototypes //////////////////
void OpenFile();
void CloseFile();
void printToFile(T *);
/////////////// Open Fringe.dat //////////////////
void OpenFile()
{
fp = fopen("fringe.dat", "a+") ;
if(fp == NULL){
printf("\"fringe.dat\" dosyasi acilamadi!") ;
exit(0) ;
}
}
//////////////// Close File /////////////////////////
void CloseFile()
{
fclose(fp);
}
//////// Print Node’s Board to file as a integer ////
void printToFile(T *B)
{
int n_board=0;
for(i=0;i<9;i++) n_board=n_board+((B->board[i])*(pow(10,i)));
fprintf(fp,"\n%d",n_board);
}
/////////// print our fringe on screen ////////////
void printFringe(Fptr currentPtr){
if(currentPtr==NULL)
printf("\nFringe is empty\n");
else{
while(currentPtr!=NULL){
printf(">%d",currentPtr->index);
currentPtr=currentPtr->next;
}
}
}
////////////// calculate fringe size /////////////
int Fringe_size(Fptr currentPtr){
counter=0;
if(currentPtr==NULL)
printf("\nFringe is empty\n");
else{
while(currentPtr!=NULL){
counter++;
currentPtr=currentPtr->next;
}
}
// printf("\nFRINGE SIZE = %d\n",counter);
return counter;
}
//////////// controls that fringe is empty /////////////
int emptyF(Fptr head){
return head==NULL;
}
//////// pop node our fringe – First In First Out /////////
Fptr popFIFO(Fptr *head,Fptr *tail){
Fptr f_temp;
f_temp=*head; // that we returns f_temp
*head=(*head)->next; // we shift head one step
if(*head==NULL)
*tail=NULL;
return f_temp;
}
////////// pop node our fringe – Last in First Out ////////////
Fptr popLIFO(Fptr *head,Fptr *tail){
Fptr f_temp;
f_temp=*tail; //that we returns f_temp
(*tail)=(*tail)->back; //we shift tail one step
if(*tail==NULL)
*head=NULL;
if((*tail==NULL) && (*head==NULL))
return NULL;
return f_temp;
}
/////////////////// push node our fringe ////////////////
void pushF(Fptr *head,Fptr *tail, T *node){
Fptr newptr;
newptr=malloc(sizeof(Fptr));
if(newptr != NULL) {
newptr=node;
newptr->next=NULL;
newptr->back=NULL;
if(emptyF(*head)) //if fringe is empty
*head=newptr;
else{
(*tail)->next=newptr;
newptr->back=(*tail);
}
*tail=newptr;
}
else
printf("\nInsert to Fringe is FAILED!!\n");
}
//////////////////// creates a new node ////////////////
T *createNode()
{
int i=0;
T *newNode;
newNode=(T*)malloc(sizeof(T));
if(!(newNode=(T*)malloc(sizeof(T)))) {
printf("Out of memory!\n");
exit(1);
}
inx=inx+1;
newNode->index=inx; // sets new Node’s index
newNode->depth=0; // sets new Node’s depth zero
newNode->fringe_size=0; // sets new Node’s fringe size zero
for(i=0;i<9;i++) newNode->board[i]=0;
newNode->father = NULL;
newNode->children[0] = NULL;
newNode->children[1] = NULL;
newNode->children[2] = NULL;
newNode->children[3] = NULL;
newNode->next=NULL;
return newNode;
}
//////////////// expans node in Tree ////////////////
void expand(T *old,int dir)
{
int i=0;
int temp;
int n_board[9];
T *newNode;
for(i=0;i<9;i++) n_board[i]=old->board[i];
newNode=createNode();
//////// change state ///////////
if(dir==0){ // if direction is "zero",the blank sets left
for(i=0;i<9;i++){ if(n_board[i]==0){ temp=n_board[i-1]; n_board[i-1]=0; n_board[i]=temp; } } } if(dir==1){ // if direction is "1",the blank sets right for(i=8;i>=0;i–){
if(n_board[i]==0){
temp=n_board[i+1];
n_board[i+1]=0;
n_board[i]=temp;
}
}
}
if(dir==2){ // if direction is "2",the blank sets top
for(i=0;i<9;i++){ if(n_board[i]==0){ temp=n_board[i-3]; n_board[i-3]=0; n_board[i]=temp; } } } if(dir==3){ // if direction is "3",the blank sets bottom for(i=8;i>=0;i–){
if(n_board[i]==0){
temp=n_board[i+3];
n_board[i+3]=0;
n_board[i]=temp;
}
}
}
for(i=0;i<9;i++) newNode->board[i]=n_board[i];
newNode->father = old;
newNode->depth=(old->depth+1); // newnode’s depth is father’s +1
// if node is not repeated or it is Bidirectional Search
if((checkRepeated(newNode) == 0) || (check_BS==1)){
if((limit==0) || (limit>=newNode->depth)){
// this if statement is for depth limited search
// if limit equals zero it means there is not depth limit search
old->children[dir] = newNode; // newnode is old node’s child
OpenFile();
printToFile(newNode);
CloseFile();
// push newnode in our fringe
if((swap%2)==0)
pushF(&head,&tail,newNode);
if((swap%2)==1)
pushF(&Ghead,&Gtail,newNode);
newNode->fringe_size= Fringe_size(head);
//calculate our fringe size
}
}
}
/////////// Checks for goal state ///////////
int checkGoal(T *B)
{
int c_board[9];
counter=0;
for(i=0;i<9;i++) c_board[i]=B->board[i];
for(i=0;i<9;i++){ if(c_board[i]==goal_state[i]) counter++; } //if counter is 9 it is goal state if(counter==9){ printf("\nALGORITHM FOUND THE GOAL STATE"); printstate(B); while(B->father!=NULL){
B=B->father;
printstate(B);
}
return 0; //it is goal state
}
else
return 1; //it is not goal state
}
/*
* Checks for goal state in Bidirectional Search
* 1 – it is not goal state
* 0 – it is goal state
*/
int checkGoal_BS(T *B , T *G)
{
T *GF;
counter=0;
GF=G->father;
for(i=0;i<9;i++){ if(B->board[i]==(G->board[i]))
counter++;
}
if(counter==9){
printf("\nALGORITHM FOUND THE GOAL STATE");
printstate(B);
while(B->father!=NULL){
B=B->father;
printstate(B);
}
return 0;
}
counter=0;
if(GF!=NULL){
for(i=0;i<9;i++){ if(B->board[i]==(GF->board[i]))
counter++;
}
if(counter==9){
printf("\nALGORITHM FOUND THE GOAL STATE");
printstate(B);
while(B->father!=NULL){
B=B->father;
printstate(B);
}
return 0;
}
}
if(GF!=NULL){
for(j=0;j<4;j++){ counter=0; if((GF->children[j])!=NULL){
for(i=0;i<9;i++){ if(B->board[i]==(GF->children[j]->board[i]))
counter++;
}
if(counter==9){
printf("\nALGORITHM FOUND THE GOAL STATE");
printstate(B);
while(B->father!=NULL){
B=B->father;
printstate(B);
}
return 0;
}
}
}
}
return 1;
}
//////////// Checks for repeated state //////////
int checkRepeated(T *node) {
int counter=0;
int board;
int n_board=0;
// convert board as integer
for(i=0;i<9;i++) n_board=n_board+((node->board[i])*(pow(10,i)));
OpenFile(); //open file
while(!feof(fp)){ // search file
fscanf(fp,"%d",&board);
if(board==n_board){
CloseFile();
return 1; // node is expanded before
}
}
CloseFile();
return 0; // node is not repeated
}
//////// solve Breadth First Search ////////////
void startSolve_BFS(T *B)
{
int c;
T *tmp;
T *f;
tmp=B;
c=checkGoal(tmp);//if it is "zero" end the program
if(c==0){
getch();
exit(1);
}
if(c!=0){ // if state is not repeated
for(i=0;i<9;i++){ if(tmp->board[i]==0){
if(i==0){
expand(tmp,1);
expand(tmp,3);
}
if(i==1){
expand(tmp,0);
expand(tmp,1);
expand(tmp,3);
}
if(i==2){
expand(tmp,0);
expand(tmp,3);
}
if(i==3){
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==4){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==5){
expand(tmp,0);
expand(tmp,2);
expand(tmp,3);
}
if(i==6){
expand(tmp,1);
expand(tmp,2);
}
if(i==7){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
}
if(i==8){
expand(tmp,0);
expand(tmp,2);
}
}
}
f=popFIFO(&head,&tail); //pop node in our fringe
startSolve_BFS(f);
}
}
//////// solve Depth First Search ////////////
void startSolve_DFS(T *B)
{
int c;
T *tmp;
T *f;
tmp=B;
c=checkGoal(tmp);//if it is "zero" end the program
if(c==0){
getch();
exit(1);
}
if(c!=0){ // if state is not repeated
for(i=0;i<9;i++){ if(tmp->board[i]==0){
if(i==0){
expand(tmp,1);
expand(tmp,3);
}
if(i==1){
expand(tmp,0);
expand(tmp,1);
expand(tmp,3);
}
if(i==2){
expand(tmp,0);
expand(tmp,3);
}
if(i==3){
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==4){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==5){
expand(tmp,0);
expand(tmp,2);
expand(tmp,3);
}
if(i==6){
expand(tmp,1);
expand(tmp,2);
}
if(i==7){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
}
if(i==8){
expand(tmp,0);
expand(tmp,2);
}
}
}
f=popLIFO(&head,&tail); //pop node from our fringe
if(f==NULL){
printf("\nCAN NOT SOLVE PROBLEM WITH DEPTH FIRST SEARCH!!!\n");
exit(1);
}
startSolve_DFS(f);
}
}
//////// solve Depth limited Search ////////////
void startSolve_DL(T *B){
int c;
T *tmp;
T *f;
tmp=B;
c=checkGoal(tmp);//if it is "zero" end the program
if(c==0){
getch();
exit(1);
}
if(c==1){ // if state is not repeated
for(i=0;i<9;i++){ if(tmp->board[i]==0){
if(i==0){
expand(tmp,1);
expand(tmp,3);
}
if(i==1){
expand(tmp,0);
expand(tmp,1);
expand(tmp,3);
}
if(i==2){
expand(tmp,0);
expand(tmp,3);
}
if(i==3){
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==4){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==5){
expand(tmp,0);
expand(tmp,2);
expand(tmp,3);
}
if(i==6){
expand(tmp,1);
expand(tmp,2);
}
if(i==7){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
}
if(i==8){
expand(tmp,0);
expand(tmp,2);
}
}
}
f=popLIFO(&head,&tail); //pop node from our fringe
if(f==NULL){
printf("\nCAN NOT SOLVE PROBLEM WITH %d LIMITED DEPTH!!!\n",limit);
exit(1);
}
startSolve_DL(f);
}
}
//////// solve Iterative Deeping Search ////////////
void startSolve_IDS(T *B){
int c;
T *tmp;
T *f;
tmp=B;
c=checkGoal(tmp);//if it is "zero" end the program
if(c==0){
getch();
exit(1);
}
if(c!=0){
for(i=0;i<9;i++){ if(tmp->board[i]==0){
if(i==0){
expand(tmp,1);
expand(tmp,3);
}
if(i==1){
expand(tmp,0);
expand(tmp,1);
expand(tmp,3);
}
if(i==2){
expand(tmp,0);
expand(tmp,3);
}
if(i==3){
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==4){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==5){
expand(tmp,0);
expand(tmp,2);
expand(tmp,3);
}
if(i==6){
expand(tmp,1);
expand(tmp,2);
}
if(i==7){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
}
if(i==8){
expand(tmp,0);
expand(tmp,2);
}
}
}
f=popLIFO(&head,&tail);
if(f==NULL){
printf("\nCAN NOT SOLVE PROBLEM WITH %d LIMITED DEPTH!!!\n",limit);
limit++; //increased the limit
pushF(&head,&tail,root); //push root to our fringe
f=popFIFO(&head,&tail);
// open and close to file for empty the file
fp = fopen("fringe.dat", "w+") ;
fclose(fp);
startSolve_IDS(f); // start to solve again with new limit
}
startSolve_IDS(f);
}
}
//////// solve Bidirectional Search ////////////
void startSolve_BS(T *B, T *G){
int c;
T *tmp;
T *f;
T *g;
tmp=B;
check_BS=1;
// We have 2 start node
// first is our random state, second is our goal state
c=checkGoal_BS(tmp,G);//if it is "zero" end the program
if(c==0){
getch();
exit(1);
}
if(c!=0){ // if state is not repeated
for(i=0;i<9;i++){ if(tmp->board[i]==0){
if(i==0){
expand(tmp,1);
expand(tmp,3);
}
if(i==1){
expand(tmp,0);
expand(tmp,1);
expand(tmp,3);
}
if(i==2){
expand(tmp,0);
expand(tmp,3);
}
if(i==3){
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==4){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
expand(tmp,3);
}
if(i==5){
expand(tmp,0);
expand(tmp,2);
expand(tmp,3);
}
if(i==6){
expand(tmp,1);
expand(tmp,2);
}
if(i==7){
expand(tmp,0);
expand(tmp,1);
expand(tmp,2);
}
if(i==8){
expand(tmp,0);
expand(tmp,2);
}
}
}
// we have 2 fringe
swap++; //use integer swap to select fringe
if((swap%2)==0){
f=popFIFO(&head,&tail); //pop first node from first fringe
g=popLIFO(&Ghead,&Gtail); //pop second node to solve BS
pushF(&Ghead,&Gtail,g); //push it for use second step
startSolve_BS(f,g);
}
if((swap%2)==1){
g=popFIFO(&Ghead,&Gtail); //pop first node from second fringe
f=popLIFO(&head,&tail);
pushF(&head,&tail,f);
startSolve_BS(g,f);
}
}
}
/////////// prints state on screen ////////////
void printstate(T *B){
printf("\n*********************");
for(i=0;i<9;i++){ if(i%3==0) printf("\n"); printf("%d\t",B->board[i]);
}
printf("\n*********************\n");
printf("NODE’s DEPTH : %d\n",B->depth);
printf("NODE’s Fringe Size : %d\n",B->fringe_size);
}
/////// creates our first random state //////////
T *randomState()
{
int direction,temp,a;
int rand_state[9];
T *newNode;
T *GNode;
newNode = createNode();
GNode = createNode();
for(i=0;i<9;i++) //equal random state with goal state
rand_state[i]=goal_state[i];
k=rand()%10+10; // generate random move between 10 and 20
printf("Number of move to generate first state random is %d\n",k);
for(j=0;j<k;j++)
{
for(a=0;a<10;a++){
if(rand_state[a]==0) // find which element is zero in state
break;
}
if(a==0){ // if first element is zero
direction=rand()%2; // generate random direction
if(direction==0){
temp=rand_state[1];
rand_state[1]=rand_state[0];
rand_state[0]=temp;
}
if(direction==1){
temp=rand_state[3];
rand_state[3]=rand_state[0];
rand_state[0]=temp;
}
}
if(a==1){ // if second element is zero
direction=rand()%3;
if(direction==0){
temp=rand_state[1];
rand_state[1]=rand_state[0];
rand_state[0]=temp;
}
if(direction==1){
temp=rand_state[2];
rand_state[2]=rand_state[1];
rand_state[1]=temp;
}
if(direction==2){
temp=rand_state[1];
rand_state[1]=rand_state[4];
rand_state[4]=temp;
}
}
if(a==2){ // if third element is zero
direction=rand()%2;
if(direction==0){
temp=rand_state[2];
rand_state[2]=rand_state[1];
rand_state[1]=temp;
}
if(direction==1){
temp=rand_state[2];
rand_state[2]=rand_state[5];
rand_state[5]=temp;
}
}
if(a==3){ // if fourth element is zero
direction=rand()%3;
if(direction==0){
temp=rand_state[3];
rand_state[3]=rand_state[0];
rand_state[0]=temp;
}
if(direction==1){
temp=rand_state[3];
rand_state[3]=rand_state[4];
rand_state[4]=temp;
}
if(direction==2){
temp=rand_state[3];
rand_state[3]=rand_state[6];
rand_state[6]=temp;
}
}
if(a==4){ // if fifth element is zero
direction=rand()%4;
if(direction==0){
temp=rand_state[4];
rand_state[4]=rand_state[1];
rand_state[1]=temp;
}
if(direction==1){
temp=rand_state[3];
rand_state[3]=rand_state[4];
rand_state[4]=temp;
}
if(direction==2){
temp=rand_state[4];
rand_state[4]=rand_state[5];
rand_state[5]=temp;
}
if(direction==3){
temp=rand_state[4];
rand_state[4]=rand_state[7];
rand_state[7]=temp;
}
}
if(a==5){ // if sixth element is zero
direction=rand()%3;
if(direction==0){
temp=rand_state[5];
rand_state[5]=rand_state[2];
rand_state[2]=temp;
}
if(direction==1){
temp=rand_state[5];
rand_state[5]=rand_state[4];
rand_state[4]=temp;
}
if(direction==2){
temp=rand_state[5];
rand_state[5]=rand_state[8];
rand_state[8]=temp;
}
}
if(a==6){ // if seventh element is zero
direction=rand()%2;
if(direction==0){
temp=rand_state[6];
rand_state[6]=rand_state[3];
rand_state[3]=temp;
}
if(direction==1){
temp=rand_state[6];
rand_state[6]=rand_state[7];
rand_state[7]=temp;
}
}
if(a==7){ // if eightth element is zero
direction=rand()%3;
if(direction==0){
temp=rand_state[7];
rand_state[7]=rand_state[4];
rand_state[4]=temp;
}
if(direction==1){
temp=rand_state[7];
rand_state[7]=rand_state[6];
rand_state[6]=temp;
}
if(direction==2){
temp=rand_state[7];
rand_state[7]=rand_state[8];
rand_state[8]=temp;
}
}
if(a==8){ // if nineth element is zero
direction=rand()%2;
if(direction==0){
temp=rand_state[8];
rand_state[8]=rand_state[5];
rand_state[5]=temp;
}
if(direction==1){
temp=rand_state[8];
rand_state[8]=rand_state[7];
rand_state[7]=temp;
}
}
}
for(i=0;i<9;i++) newNode->board[i]=rand_state[i];
/*
newNode->board[0]=1;
newNode->board[1]=3;
newNode->board[2]=4;
newNode->board[3]=8;
newNode->board[4]=2;
newNode->board[5]=5;
newNode->board[6]=7;
newNode->board[7]=6;
newNode->board[8]=0;
*/
for(i=0;i<9;i++) GNode->board[i]=goal_state[i];
printf("\n—->FIRST STATE<—-"); printstate(newNode); // print our random state root = newNode; pushF(&head,&tail,root); // push root our fringe pushF(&Ghead,&Gtail,GNode); return root; } int main() { int secim; T *s; T *g; fp = fopen("fringe.dat", "w+") ; fclose(fp); srand(time(NULL)); randomState(); s=popFIFO(&head,&tail); g=popFIFO(&Ghead,&Gtail); pushF(&Ghead,&Gtail,g); printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
printf("\nSelect Algorithm to solve");
printf("\n[1] Breadth First Search");
printf("\n[2] Depth First Search");
printf("\n[3] Depth limited Search");
printf("\n[4] Iterative Deepening Search");
printf("\n[5] Bidirectional Search\n");
printf("Enter number of your choice : ");
scanf("%d",&secim);
switch(secim){
case 1:
startSolve_BFS(s);
Fringe_size(head);
break;
case 2:
startSolve_DFS(s);
Fringe_size(head);
break;
case 3:
printf("\nENTER THE DEPTH LIMIT:");
scanf("%d",&limit);
startSolve_DL(s);
break;
case 4:
limit=1;
startSolve_IDS(s);
break;
case 5:
startSolve_BS(s,g);
break;
default:
printf("\nWRONG CHOICE!!");
}
CloseFile();
}
[/sourcecode]
Yanıt Bırak