Download Techniques to solve AI problems

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Gene expression programming wikipedia , lookup

Catastrophic interference wikipedia , lookup

Rete algorithm wikipedia , lookup

Minimax wikipedia , lookup

Hierarchical temporal memory wikipedia , lookup

Transcript
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