Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Implementing the Astar Algorithm In solving the Eight Puzzle problem By Sriram Rajan Team Members Cody Kutac Harish Vuyurru TABLE OF CONTENTS INTRODUCTION TO AI .................................................................... 1 TECHNIQUES TO SOLVE AI PROBLEMS .......................................... 2 PROBLEM DESCRIPTION ................................................................ 3 THE EIGHT-PUZZLE PROBLEM ..................................................................................... 3 PROBLEM STATEMENT .................................................................................................. 3 THE ASTAR ALGORITHM ................................................................... 4 THE ALGORITHM ............................................................................................................ 4 DATA STRUCTURES & FUNCTIONS .............................................................................. 5 IMPLEMENTATION TECHNIQUE......................................................................................... 6 PSEUDOCODE ................................................................................................................... 7 NODE GENERATION ....................................................................................................... 8 HEURISTIC SEARCHING TECHNIQUES............................................ 9 THE FIRST HEURISTIC ................................................................................................... 9 MY HEURISTIC ............................................................................................................... 10 OBSERVATION & ANALYSIS .......................................................... 11 APPENDIX .................................................................................... 12 WORK DISTRIBUTION .................................................................................................. 12 SOURCE CODE ............................................................................................................. 13 SAMPLE OUTPUT .......................................................................................................... 26 REFERENCES ............................................................................... 29 Introduction to AI “Artificial Intelligence is the study of how to make computers do things, which at the moment; people do better” [Rich & Knight]. Computers can do many wonderful things. They can perform calculations millions or billions of times faster than human beings. In the past, computer scientists have created a great many programs that could perform tasks that people wouldn't have otherwise believed a computer could do. This is not limited to only playing chess, or proving theorems, but also programs that can hold a regular conversation with humans, understand stories and perform many other humanlike tasks. Yet, there have also been very many legitimate questions whether or not the intelligence that these programs exhibit can be comparable to human intelligence. The problem lies with architecture, the way our programs are structured. Alan Turing, one of the fathers of AI, once created a theorem that stipulated that all computers (he uses the term Turing machines, which can be likened to digital computers) could compute anything that is computable [1]. AI addresses one of the ultimate puzzles. How is it possible for a slow, tiny brain, whether biological or electronic, to perceive, understand, predict, and manipulate a world far larger and more complicated than itself? How do we go about making something with those properties? These are hard questions, but unlike the search for faster-than-light travel or an antigravity device, the researcher in AI has solid evidence that the quest is possible. All the researcher has to do is look in the mirror to see an example of an intelligent system. Artificial Intelligence is a very dynamic field. Although lots of research has been done in the field of AI, It is a field of study that is very far from saturation with a huge area left unexplored and waiting to be studied and analyzed. 1 Techniques to solve AI problems Broadly AI systems can be divided into the following categories Systems that think like humans: The cognitive modeling approach Systems that think rationally: The laws of thought approach Systems that act like humans: The rational agent approach Systems that act rationally: The rational agent approach Almost all AI problems have the following characteristics It is Voluminous It is hard to characterize accurately It is constantly changing It differs from data by being organized in a way that corresponds to the way it will be used The three most important AI techniques that help to solve the above problems are Search Provide a way of solving problems for which no more direct approach is available as well as a framework into which any direct techniques that are available can be embedded. This is the field of heuristic (intelligent) searching. The idea is to apply human intelligence in programs to search in unconventional ways Use of Knowledge and Reasoning Provides an intelligent way of solving complex problems by exploiting the data structures of the objects that are involved. Make the programs think like humans. Analyze how humans solve a particular problem and apply similar human reasoning in programs. Abstraction The idea of abstraction is to separate the important features from the unimportant features that would otherwise overwhelm the process and unnecessarily increase the complexity. Study the problem to detect areas that need not be processed by the program thus saving time and memory. 2 Problem Description The Eight-Puzzle problem A good example of a search problem is the 8 piece puzzle. This is a simple sliding tile puzzle on a 3*3 grid where one tile is missing and you can move the other tiles into the gap until you get the puzzle into the goal position. The following figures show different states of an eight-piece puzzle. The solved puzzle is the final state while the remaining two are in unsolved state. The rules of the game are that we need to move the blank tile either left, right, top, center (depending upon its position) so as to achieve the final state. The arrows indicate the possible moves for the blank tile. The blank tile needs to be moved till we reach the solved state. Solved Puzzle Unsolved Puzzle Unsolved Puzzle 1 2 3 3 5 8 4 8 7 6 5 7 1 1 6 3 4 8 4 6 5 7 2 2 Problem Statement Implement the Astar algorithm (explained in the next section) in solving the eight puzzle problem. There should be a total of six heuristic functions out of which three should be admissible (explained in the proceeding sections). Solve the eight-puzzle problem for two different initial states using six heuristics functions (explained in the proceeding sections). Tabulate the results in terms of the number of nodes generated, number of nodes expanded, depth of the tree, effective branching factor and cost of the path and the execution time. The two initial states for consideration are 2 8 3 2 1 6 1 6 4 4 8 7 5 7 5 3 3 The Astar Algorithm The Algorithm Start with OPEN containing only the initial node. Set the node’s g value to 0, its h’ value to whatever it is, and its f’ value to h’+0, or h’. Set CLOSED to the empty list. Until a goal node is found, repeat the following procedure: If there are no nodes on OPEN, report failure. Otherwise, pick the node on OPEN with the lowest f’ value. Call it bestnode. Remove it from OPEN. Place it on CLOSED. See if bestnode is a goal node. If so, exist and report a solution (either bestnode if all we want is the node or the path that has been created between the initial state and bestnode if we are interested in the path.) Otherwise, generate the successors of bestnode but do not set bestnode to point to them yet. For each such successor do the following: o Set successor to point back to bestnode. These backwards links will make it possible to recover the path once a solution is found. Compute g(successor) = g(bestnode) + the cost of getting form bestnode to successor. See if successor is the same as any node on OPEN (i.e. it has already been generated but not preceded). If so, call that node old. Since this node already exists in the graph, we can throw successor away and add old to this list of bestnode’s successors. Now we must decide whether old’s parent link should be reset to point to bestnode. It should be if the path we have just found to successor is cheaper than the current best path to old (since successor and old are really the same node). So see whether it is cheaper to get to old via its current parent or to successor via bestnode by comparing their g values. If old is cheaper (or just as cheap), then we need do nothing. If successor is cheaper, then reset old’s parent link to point to bestnode, record the new path in g(old), and update f’(old). If successor was not on OPEN, see if it is on CLOSED. If so, call the node on CLOSED old and add old to the list of bestnode’s successors. Check to see if the new path or the old path is better just as in step(2c), and set the parent link and g and f’ values appropriately. If we have just found a better path to old, we must propagate the improvement to old’s successors. This is a bit tricky. Old points to its successors. Each successor in turn points to its successors, and so forth, until each branch terminates with a node that either is still on OPEN or has no successors. So to propagate the new cost download, do a depth-first traversal of the tree starting at old, changing each node’s g value (and thus also its f’ value), terminating each branch when you reach either a node with no successors or a node to which an equivalent or better path has already been found. 4 If successor was not already on either open or closed, then put it on open and add it to the list of bestnode’s successors. Compute f’(successor) = g(successor) + h’(successor). The A* algorithm is ideal for finding optimal paths between cells in the two-dimensional, grid-based world. Astar is an optimal algorithm that always uses admissible heuristics for searching. However for most problems, the number of nodes within the goal search space is exponential in the length of the solution. The exponential growth will occur unless the error in the heuristic function grows no faster than the logarithm of the actual path cost. Data Structures & Functions The OPEN list of the Astar is implemented using a priority queue. A priority queue is more suitable because we need to pick the State with least F in order to proceed downwards. Other possible data structures that can be used are heaps. The OPEN list stores the states that were generated but not expanded. This is helpful since if we find a successor state that is already in OPEN we can discard it and use the one in the open. The CLOSED list is implemented using a simple linked list. A simple linked list is sufficient since all we need to do is store the nodes that have been processed The nodes are stored in form of a tree. One variation here could be to implement the nodes as a graph. A graph implementation would be a bit more complicated though it would save space as we duplicate states wont be stored. In the case of the eight-puzzle the number of nodes that will be generated during the astar search are considerably less and hence a tree representation is sufficient. The above data structures were implemented using the c++ standard template library. G : Function G is a measure if the cost of getting from the initial state to the current node F : The true evaluation of the node H : The actual cost of getting from the current node to the goal H’ : Is an estimate of the cost 5 Implementation Technique The idea is to search the state space and find the shortest route to the goal state. During the search we need to keep track of two lists of states. The first list is the OPEN list, which stores nodes, which we have generated by using the rules from an existing node, but we don't yet know where they lead to. The second list is the CLOSED list, which contains the nodes, we have generated and we have also explored where they go. Each state is stored along with some extra data required to help us in our search. The first thing that is required is a parent pointer. We need to know how we got to this node, as the end result of finding the GOAL state will be to generate a path back to the start. Tracking which node parented this node allows doing this. The node also has three ratings used during the search, which are the cost of the node, the heuristic estimate of this node, and ‘f’, which is the total of the other two. The heuristic estimate can be much more complex. We can guess how good the node is by how near it is to the GOAL. This works well on the tiled maze. In practice though the more help you give the algorithm the better. Finally the 'f' rating of a node, which represents how good it is in terms of, how much it cost to get there and how near to the goal we are, is used throughout the search to always follow the most promising path. 6 Pseudocode bool AStarSearch() { priorityqueue OPEN list CLOSED BestNode = initial // this is the body of the search while OPEN is not empty { if BestNode is a goal node { construct path (by following the parent pointers) return success } else Generate successors of BestNode For all successors of BestNode do if the successor is not in open push it to open Pop the first node from OPEN and set it to Bestnode //this will the one with least F Push the popped node onto CLOSED list } if we got here we emptied the OPEN list and found no GOAL states report search failed 7 Node Generation A sample node generation is shown. Assume the root state is the initial state and the heuristic used is H1(n) – Number of displaced tiles.. We generate the successors from each state and then pick the successor with the lowest F. 2 1 * 8 6 7 3 4 5 F=6 F=5 2 8 6 7 * 1 F=7 2 3 4 5 8 6 * 1 7 F=7 F=7 3 4 5 F=6 F=7 F=7 * 8 3 2 8 3 2 8 3 2 8 3 2 8 3 2 8 3 2 1 6 7 4 5 6 1 * 7 4 5 1 * 6 7 4 5 1 7 * 6 4 5 1 * 6 7 4 5 1 7 6 5 4 * 8 Heuristic Searching Techniques Intelligence for a system with limited processing resources consists in making wise choices of what to do next [Luger &Stublefield Pg116]. Heuristic can be traced to Greek for eurisco (“I discover”). A problem may not have an exact solution because of inherent ambiguities in the problem statement or available data. Or a problem may have an exact solution, but computational cost of finding it may be prohibitive (Ex : games like chess). By eliminating states a heuristic algorithm can defeat combinatorial explosion and find an acceptable solution. A heuristic like any discovery is fallible and is only an informed guess of the next step to be taken in solving the problem. Admissibility The restriction on a heuristic is that ideally it should be admissible. A heuristic is admissible if it never over estimates the cost to reach the goal. Any graph search algorithm is said to be admissible if it always returns an optimal solution, that is the one with the lowest cost, if a solution exists at all. Such a heuristic search when applied to total cost search is an Astar search. Astar always uses admissible heuristics. In the implementation we have used two heuristics. One of these heuristics is admissible while the other. The first Heuristic H1(n) = Number of displaced titles ( the blank tile is not counted) 2 8 3 2 1 6 1 6 4 4 8 7 5 7 5 3 H1(n) = 5 H1(n) = 7 This Heuristic is admissible because it never over-estimates the cost. Hence using this heuristic will result in an Astar search. 9 My Heuristic H2(n) = H1(n) + MyH MyH = sum of distances each displaced tile is from the blank square 2 8 3 2 1 6 1 6 4 4 8 7 5 7 5 3 H2(n) = 5 + 4 = 9 H2(n) = 6 + 5 =11 This heuristic it is not admissible and hence cannot be used in an Astar search. The value of MyH will never be greater than 16(the worst case when the sum is the greatest) hence it can be shown that it does not over-estimate the value of H by more than 2, which is somewhat closer to being admissible. Why use this heuristic Most admissible heuristics underestimate to a great extent. Even though they find the optimal solution and the search is an Astar search, there are many cases where take longer time because of the underestimation. This heuristics can be used in an interesting way as shown in the following Calculate MyH If MyH is greater than twice H1(n) the add MyH to H1(n) to calculate the new heuristics Else Discard MyH from the calculation. The comparison of the various heuristics is tabulated in the observation and analysis section. 10 Observation & Analysis Heuristic Function Initial State 1 ET NG Analysis NE D b* Sriram Rajan – Heuristic 1 Number or Misplaced tiles Sriram Rajan – Heuristic 2 Self-Created Cody Kutac – Heuristic 3 Num of misplaced tiles Cody Kutac – Heuristic 4 Self-Created Harish Vuyyurru –Heuristic5 Sum of distances from correct position Harish Vuyyurru –Heuristic 6 Self-Created 10ms 18 8 6 3 6 18ms 21 10 6 3.5 6 8ms 17 7 6 2.83 6 45ms 52 27 8 6.5 8 8ms 16 6 6 2.66 6 8ms 16 6 6 2.66 6 Initial State 2 ET NG NE D b* f* Sriram Rajan – Heuristic1 Number or Misplaced tiles Sriram Rajan – Heuristic 2 Self-Created Cody Kutac – Heuristic 3 Num of misplaced tiles Cody Kutac – Heuristic 4 Self-Created Harish Vuyyurru –Heuristic 5 Sum of distances from correct position Harish Vuyyurru –Heuristic 6 Self-Created 12 sec 2136 1884 18 174 18 6 sec 1662 1141 18 92 18 12 sec 2136 1884 18 174 18 4 sec 980 765 18 54.44 18 4 sec 989 588 18 54.94 18 4sec 989 588 18 54.94 18 f* ET – Execution time NG – Nodes Generated NE – Node Expanded D - Depth b* - branching factor 11 Appendix Work Distribution Sriram Rajan Cody Kutac Harish Vuyurru All the overloaded operators and print functions for the state & node class State class for storing a state of the eight puzzle Node class used for the storing each node of the eight puzzle Generating the possible moves from each state Printing the solution Open list and its Closed list and its functions functions Function to check if a Function to check if a node is in the open state is in closed Worked together in getting the Astar algorithm to work correctly. Checked for various inputs. Formatted the output according to the requirements The observation table on both the initial states and the individual heuristics 12 Source code /* Project : The eight-puzzle implementation using the Astar algorithm By -: Sriram Rajan Cody Kutac Harish Vuyurru File: node_state.h Contains the classes to store a node(tile) of 8 puzzle and state of nodes */ #include <iostream> #include <assert.h> #include <time.h> #define BLANK -1 #define MAXNUM 9 using namespace std; extern int puzz_solved[MAXNUM]; extern int print_sequence[MAXNUM]; //function to calculate time //returns the time in millseconds time_t gettime() { time_t t; time_t curr=time(&t); return t; } //Class to implement one node of the puzzle class Node { public: int number; // the number itself int pos; // position on the grid Node(int no, int p) { number=no; pos=p; } //overloading the output operator friend std::ostream& operator <<(std::ostream &out, Node &n); //operators used with STL to perform certain algorithms bool operator <(Node &p) { if(p.pos>pos) return true; else return false; } 13 bool operator ==(int n) { if(n==number) return true; else return false; } bool operator ==(Node n) { if(number==n.number && pos==n.pos) return true; else return false; } }; //output operator std::ostream& operator <<(std::ostream &out, Node &n) { out<<n.number<<"\t"<<n.pos; return out; } //class to store a STATE of the puzzle class State { public: list<Node> plist; //linked list containing the nine nodes //F, G, H for Astar int F; int G; int H; State *next[4]; //store child int num_next; //child count State *parent; //pointer to parent State(int g=0,int h=0) { G=g; H=h; //h comes from the heuristic function F=g+h; for(int i=0;i<4;i++) next[i]=NULL; num_next=0; parent=NULL; } //print state and their children void print(); 14 //overloaded operators for STL bool operator <(State &s) { if(s.F>F) return true; else return false; } bool operator ==(State *s) { list<Node>::iterator n_itr1, n_itr2; n_itr2=s->plist.begin(); for(n_itr1=plist.begin();n_itr1!=plist.end();n_itr1++,n_itr2++) { if(n_itr1->number!=n_itr2->number) return false; } return true; } }; void State::print() { int i=0; list<Node>::iterator l_itr; //Iterator to a linked list //PRINT STATE cout<<"---------------------\n"; for (i=0;i<MAXNUM;i++) { if(i%3==0) cout<<endl; for(l_itr=plist.begin();l_itr!=plist.end();l_itr++) //go thru the list { if(l_itr->pos==print_sequence[i]) { if(l_itr->number==BLANK) cout<<"*\t"; else cout<<l_itr->number<<"\t"; } } } cout<<"\n---------------------\n"; cout<<"G="<<G<<"\tH="<<H<<"\tF="<<F<<"\n"; } 15 /* Project : The eight puzzle implementation using the Astar algorithm By -: Sriram Rajan Cody Kutac Harish Vuyurru File: astar_8p.h Implements the Astar algorithm Also contains the Heuristics used Class Astar_8Puzzle Private members State *root; //root state..denotes begining of the Astar graph list<State> A_OPEN; //To store generated nodes list<State> A_CLOSED; //To store processed nodes State *A_bestnode; //store best node for processing char h_used[4]; //heuristic used , Ex : "H1", "H2","H3" Public Member functions *** Astar_8Puzzle(int *a,char *h);*** //Constructor Sets the root to initial state //a is an array containing the initial state of the puzzle //h is the heuristic used- Options are H1,H2,H3,H4,H5,H6 *** void Astar_Solve(); *** //Generate States and find solution // Also prints the number of nodes generated/used , branching factor etc *** void Astar_helper(State *root) *** //Helper function to generate states // Generates all possible states from a current state *** void Print() *** *** void print_open() *** *** void print_closed() *** //print all states, open and closed bool is_Goal(State *ptr); //returns if the current state is goal state bool is_Closed(State *ptr); //returns if the node is in closed bool is_OPEN(State *ptr); //returns if the node is in open //All Heuristics combined together //Depending on h_used the heuristic is selected int Heuristic(State *st); */ #include #include #include #include <iostream> <assert.h> <time.h> <math.h> 16 //Standard Template Library Headers #include <string> #include <list> #include <algorithm> #include "node_state.h" //header for node and state class //Some readable macros #define BLANK -1 #define MAXNUM 9 using namespace std; //Array for checking aand printing int puzz_solved[MAXNUM]={1,2,3,4,5,6,7,8,BLANK}; int print_sequence[MAXNUM]={1,2,3,8,9,4,7,6,5}; //Implementing the A* algorithm class Astar_8Puzzle { private: State *root; //root state..denotes begining of the Astar graph list<State> A_OPEN; //To store generated nodes list<State> A_CLOSED; //To store processed nodes State *A_bestnode; //store best node for processing char h_used[4]; //heuristic used , Ex : "H1", "H2","H3" public: //Constructor Sets the root to initial state Astar_8Puzzle(int *a,char *h); Astar_8Puzzle(){ root=NULL;} void Astar_Solve(); //Generate States and find solution void Astar_helper(State *root); //Helper function to generate states //print all states, open and closed void Print(); void print_open(); void print_closed(); bool is_Goal(State *ptr); //returns if the current state is goal state bool is_Closed(State *ptr); //returns if the node is in closed bool is_OPEN(State *ptr); //returns if the node is in open //All Heuristics combined together //Depending on h_used the heuristic is selected int Heuristic(State *st); }; Astar_8Puzzle::Astar_8Puzzle(int *a,char *h) { State *new_state; Node *new_node; new_state = new State(); //create the first state and assign it to root for (int i=0;i<MAXNUM;i++) 17 { new_node = new Node(a[i],i+1); new_state->plist.push_back(*new_node); } strcpy(h_used,h); //set the heuristic used //set G & H & F new_state->G=0; new_state->H=Heuristic(new_state); new_state->F= new_state->G + new_state->H; root=new_state; //set root } void Astar_8Puzzle::Astar_Solve() { State rptr; double bfactor; time_t stime=gettime(); //Get start time A_bestnode = root; do { if(is_Goal(A_bestnode)) { time_t etime=gettime(); //Get end time //print all details cout<< "Goal Reached !!"<<"\tHeuristic used "<<h_used<<endl; cout<<"\nExecution Time(ET) :"<<(etimestime)<<"secs\n"; cout<<"\nNumber of nodes Generated(NT):"<<A_OPEN.size()+A_CLOSED.size(); cout<<"\nNumber of nodes Expanded(NE):"<<A_CLOSED.size(); cout<<"\nDepth(d):"<<A_bestnode->G; bfactor=(double)(A_OPEN.size()+A_CLOSED.size()) / (A_bestnode->G); cout<<"\nBranching Factor(b*):"<<bfactor<<endl; cout<<"\nCost of the PATH(f*):"<<A_bestnode->F<<endl; //print the nodes from the root to the solution cout<<"Printing Solution Trace\n"; print_closed(); break; } else { Astar_helper(A_bestnode); for(int i=0;i<A_bestnode->num_next;i++) { if(!(is_OPEN(A_bestnode->next[i]))) //check if in open A_OPEN.push_back(*(A_bestnode->next[i])); } A_OPEN.sort(); //sort 18 if(A_OPEN.empty()) //if open is empty .. no solution { cout<<"Open Empty:Failed to find result!!\n"; break; } else { rptr=A_OPEN.front(); A_bestnode=&rptr; A_CLOSED.push_back(rptr); // put processed node in closed A_OPEN.pop_front(); // remove node from open } } }while(1); } void Astar_8Puzzle:: Astar_helper(State *root) { list<Node>::iterator n_itr; list<Node>::iterator temp_itr,temp2_itr; State *temp; int pos_store; int i=0; //MOVE THRU THE NODES AND FIND THE BLANK SQUARE //THEN START MOVING THE BLANK SQUARE for(n_itr=root->plist.begin();n_itr!=root->plist.end();n_itr++) { if(n_itr->number==BLANK) { pos_store=n_itr->pos; //Different positions on the GRID require diff movement //for each move create a new state same as parent //Then swap the nodes as per the moves if(pos_store!=9) { root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); swap(temp_itr->number,temp_itr++->number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; } 19 if(pos_store!=1) { root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); swap(temp_itr->number,temp_itr--->number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; } if(pos_store==2 || pos_store==4 || pos_store==6 || pos_store==8) { root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); swap(temp_itr->number,temp>plist.back().number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; } if(pos_store==1) //1st node { root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); for(temp2_itr=temp->plist.begin();temp2_itr>pos!=8;temp2_itr++); swap(temp_itr->number,temp2_itr--->number); 20 temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; } if(pos_store==9) //Center node { root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); for(temp2_itr=temp->plist.begin();temp2_itr>pos!=2;temp2_itr++); swap(temp_itr->number,temp2_itr--->number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); for(temp2_itr=temp->plist.begin();temp2_itr>pos!=4;temp2_itr++); swap(temp_itr->number,temp2_itr--->number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; root->next[i] = new State(1); root->num_next++; temp=root->next[i]; temp->plist=root->plist; temp->parent=root; 21 temp_itr=find(temp->plist.begin(),temp>plist.end(),n_itr->number); for(temp2_itr=temp->plist.begin();temp2_itr>pos!=6;temp2_itr++); swap(temp_itr->number,temp2_itr--->number); temp->H=Heuristic(temp); temp->G=root->G+1; temp->F=temp->G+temp->H; i++; } break; } } } //Function to help printing STATE and their Children void print_helper(State *st) { assert(st!=NULL); st->print(); if(st->num_next==0) return; else { cout<<"Number of Children:"<<st->num_next<<"\nPrinting Children\n"; for(int i=0;i<st->num_next;i++) print_helper(st->next[i]); } } //print all nodes void Astar_8Puzzle::Print() { cout<<"\nHeuristics Used:"<<h_used<<endl; assert(root!=NULL); print_helper(root); } //print all nodes in open void Astar_8Puzzle::print_open() { list<State>::iterator s_itr; for(s_itr=A_OPEN.begin();s_itr!=A_OPEN.end();s_itr++) s_itr->print();; } //print all nodes in closed void Astar_8Puzzle::print_closed() { list<State>::iterator s_itr; for(s_itr=A_CLOSED.begin();s_itr!=A_CLOSED.end();s_itr++) s_itr->print(); } 22 //return true if goal is reached bool Astar_8Puzzle::is_Goal(State *ptr) { list<Node>::iterator n_itr; assert(ptr!=NULL); int i=0; for(n_itr=ptr->plist.begin();n_itr!=ptr->plist.end();n_itr++,i++) { if(n_itr->number!=puzz_solved[i]) return false; } return true; } //return true if state is in open bool Astar_8Puzzle::is_OPEN(State *ptr) { list<Node>::iterator n_itr; list<State>::iterator s_itr; assert(ptr!=NULL); int i=0; for(s_itr=A_OPEN.begin();s_itr!=A_OPEN.end();s_itr++) { if(*s_itr==ptr) return true; } return false; } //return true if state is in closed bool Astar_8Puzzle::is_Closed(State *ptr) { list<Node>::iterator n_itr; list<State>::iterator s_itr; assert(ptr!=NULL); int i=0; for(s_itr=A_CLOSED.begin();s_itr!=A_CLOSED.end();s_itr++) { if(*s_itr==ptr) return true; } return false; } 23 //Sriram Rajan’s Heuristic functions int Astar_8Puzzle:: Heuristic(State *st) { int calc_H,num_disp=0,i=0,blank_dist=0;; list<Node>::iterator n_itr; list<Node>::iterator t_itr; //heuristic -- Admissible--number of displaced tiles if(strcmp(h_used,"H1")==0) { for(n_itr=st->plist.begin();n_itr!=st->plist.end();n_itr++) { if(n_itr->number!=puzz_solved[i] && n_itr>number!=BLANK) num_disp++; i++; } calc_H=num_disp; } //My heuristic if(strcmp(h_used,"H2")==0) { for(n_itr=st->plist.begin();n_itr!=st->plist.end();n_itr++) { if(n_itr->number!=puzz_solved[i] && n_itr>number!=BLANK) { num_disp++; t_itr=find(st->plist.begin(),st>plist.end(),BLANK); blank_dist+=abs(t_itr->pos - n_itr->number); } i++; } calc_H=num_disp + blank_dist/2; } return calc_H; } 24 #include<iostream> #include "astar_8p.h" //sample main int main() { //some start states int initial1[9]= { 2,8,3,4,5,7,BLANK,1,6}; //Dr.Ali -1 int initial2[9]= { 2,1,6,8,3,5,7,4,BLANK}; //Dr.Ali -2 //pass array and which Heuristics to use cout<<"*****Initial State-1-- H1 **********\n"; Astar_8Puzzle p1(initial1,"H1"); p1.Astar_Solve(); cout<<"*****Initial State-2-- H1 **********\n"; Astar_8Puzzle p2(initial2,"H1"); p2.Astar_Solve(); cout<<"*****Initial State-1-- H2 **********\n"; Astar_8Puzzle p3(initial1,"H2"); p3.Astar_Solve(); cout<<"*****Initial State-2-- H2 **********\n"; Astar_8Puzzle p4(initial2,"H2"); p4.Astar_Solve(); return 1; } 25 Sample Output *****Initial State-1 ********** Goal Reached !! Heuristic used H1 Execution Time(ET) :10msecs Number of nodes Generated(NT):18 Number of nodes Expanded(NE):8 Depth(d):6 Branching Factor(b*):3 Cost of the PATH(f*):6 Printing Solution Trace --------------------2 8 3 1 6 4 7 * 5 --------------------G=1 H=4 F=5 --------------------2 8 3 1 * 4 7 6 5 --------------------G=2 H=3 F=5 --------------------2 8 3 * 1 4 7 6 5 --------------------G=3 H=3 F=6 --------------------2 * 3 1 8 4 7 6 5 --------------------G=3 H=3 F=6 --------------------* 2 3 1 8 4 7 6 5 --------------------G=4 H=2 F=6 --------------------1 2 3 * 8 4 7 6 5 --------------------G=5 H=1 F=6 26 --------------------1 2 3 8 * 4 7 6 5 --------------------G=6 H=0 F=6 *****Initial State-1 ********** Goal Reached !! Heuristic used H2 Execution Time(ET) :18msecs Number of nodes Generated(NT):21 Number of nodes Expanded(NE):10 Depth(d):6 Branching Factor(b*):3.5 Cost of the PATH(f*):6 Printing Solution Trace --------------------2 8 3 1 6 4 7 * 5 --------------------G=1 H=9 F=10 --------------------2 8 3 1 6 4 7 5 * --------------------G=2 H=10 F=12 --------------------2 8 3 1 6 4 * 7 5 --------------------G=2 H=11 F=13 --------------------* 2 3 1 8 4 7 6 5 --------------------G=4 H=5 F=9 --------------------1 2 3 * 8 4 7 6 5 --------------------G=5 H=1 F=6 --------------------- 27 1 2 3 8 * 4 7 6 5 --------------------G=6 H=0 F=6 28 References Artificial Intelligence By Elaine Rich & Kevin Knight Artificial Intelligence A Modern Approach By Stuart Russel & Peter Norweigh AI by Lugger & Stubblefield http://www.aaai.org/ 29