Академический Документы
Профессиональный Документы
Культура Документы
Shraddha Muralidhar/1BM15CS143
1 8 Puzzle Problem 3
1.1 Theory: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3 A* search algorithm 9
3.1 Theory: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4 Unification Algorithm 11
4.1 Theory: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2 Code: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1
Chapter 1
8 Puzzle Problem
1.1 Theory:
An 8-puzzle consists of a 3*3 grid with the numbers 1 to 8, and one empty space
which is called the slider. The objective is to arrive at a particular goal state, which
is usually the one demonstrated above, which we will be using for this problem.
The slider can only move adjacently left, right, above and below. There are three
approaches to this, and in each approach we will evaluate the best among each set
of possibilities through a Depth First Search Tree.
• Heuristic approach: Check the number of spaces each number needs to move
to achieve the goal state, at every stage.
• Combined approach: Here we check the number of spaces that only the num-
bers adjacent to the slider need to move to achieve the goal state. This is the
most efficient approach.
1.2 Code
a =[1 ,2 ,3 ,4 ,5 ,0 ,7 ,8 ,6]
b=[1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,0]
h=[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0]
p=0# t o s t o r e p o s i t i o n o f 0
lm=0# t o s t o r e t h e value o f t h e l a s t moved b l o c k
def h e u r i s t i c ( ) :
3
4 Chapter 1. 8 Puzzle Problem
global p , h
f o r i i n range ( l e n ( a ) ) :
if a[ i ]!=0:
h[ a [ i ]]=0
f o r j i n range ( l e n ( b ) ) :
if a[ j ]!=0:
i f a[ j ]!=b[ j ] :
f o r k i n range ( l e n ( b ) ) :
i f a [ j ]==b [ k ] :
h [ a [ j ] ] = abs ( i n t ( k /3)− i n t ( j /3) ) +abs ( ( k%3)
−( j %3) )
else :
h[ a [ j ]]=0
else :
p= i
return h
def proc ( i ) :
g l o b a l p , h , lm
np=p
minimum=6
p r i n t("−−−−−Move No . : " , i ,"−−−−−")
c r = i n t ( p/3)
c c =p%3
i f cr !=2:
p r i n t ( "Down= " , a [ p + 3 ] )
i f h [ a [ p+3]] <minimum and h [ a [ p + 3 ] ] ! = 0 and lm ! = a [ p + 3 ] :
minimum=h [ a [ p + 3 ] ]
np=p+3
i f cr !=0:
p r i n t ( " Up= " , a [ p − 3])
i f h [ a [ p − 3]] <minimum and h [ a [ p − 3 ] ] ! = 0 and lm ! = a [ p − 3] :
minimum=h [ a [ p − 3]]
np=p−3
i f cc ! = 2 :
p r i n t ( " Right = " , a [ p + 1 ] )
i f h [ a [ p+1]] <minimum and h [ a [ p + 1 ] ] ! = 0 and lm ! = a [ p + 1 ] :
minimum=h [ a [ p + 1 ] ]
np=p+1
i f cc ! = 0 :
p r i n t ( " L e f t = " , a [ p − 1])
i f h [ a [ p − 1]] <minimum and h [ a [ p − 1 ] ] ! = 0 and lm ! = a [ p − 1]:
minimum=h [ a [ p − 1]]
np=p−1
i f minimum==6:
i f h==[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0]:
p r i n t ( " Solved " )
else :
p r i n t ( " Dead End " )
return 0
else :
a [ p ] , a [ np]= a [ np ] , a [ p ]
1.3. Output 5
lm=a [ p ]
p r i n t ( " Block Moved : " , lm )
p r i n t ( " Current S t a t e : " , a )
h1= h e u r i s t i c ( )
print (" Heuristic : " ,h)
p r i n t ( " P o s i t i o n Of Blank : " , p )
return 1
def main ( ) :
global p
print (" I n i t i a l State : " , a )
h1= h e u r i s t i c ( )
print (" Heuristic : " ,h)
p r i n t ( " P o s i t i o n Of Blank : " , p )
c =1
i =0
while c ! = 0 :
i = i +1
c=proc ( i )
main ( )
1.3 Output
I n i t i a l State : [1 , 2 , 3 , 4 , 5 , 0 , 7 , 8 , 6]
Heuristic : [0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0]
P o s i t i o n Of Blank : 5
−−−−−Move No . : 1 −−−−−
Down= 6
Up= 3
Left= 5
Block Moved : 6
Current S t a t e : [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 0]
Heuristic : [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0]
P o s i t i o n Of Blank : 8
−−−−−Move No . : 2 −−−−−
Up= 6
Left= 8
Solved
Chapter 2
There are two common ways to traverse a graph, BFS and DFS. Considering a Tree
(or Graph) of huge height and width, both BFS and DFS are not very efficient due
to following reasons.
• DFS first traverses nodes going through one adjacent of root, then next adja-
cent. The problem with this approach is, if there is a node close to root, but
not in first few subtrees explored by DFS, then DFS reaches that node very
late. Also, DFS may not find shortest path to a node (in terms of number of
edges).
• BFS goes level by level, but requires more space. The space required by DFS
7
8 Chapter 2. Iterative Deepening Search
is O(d) where d is depth of tree, but space required by BFS is O(n) where n
is number of nodes in tree (Why? Note that the last level of tree can have
around n/2 nodes and second last level n/4 nodes and in BFS we need to
have every level one by one in queue).
2.1 Theory:
IDDFS combines depth-first search’s space-efficiency and breadth-first search’s fast
search (for nodes closer to root).DDFS calls DFS for different depths starting from
an initial value. In every call, DFS is restricted from going beyond given depth. So
basically we do DFS in a BFS fashion.
2.2 Code
// Returns t r u e i f t a r g e t i s r e a c h a b l e from
// s r c within max_depth
bool IDDFS ( s r c , t a r g e t , max_depth )
f o r l i m i t from 0 t o max_depth
i f DLS ( s r c , t a r g e t , l i m i t ) == t r u e
return true
return f a l s e
bool DLS ( s r c , t a r g e t , l i m i t )
i f ( s r c == t a r g e t )
return true ;
return f a l s e
2.3 Output
A* search algorithm
A* search is an informed search algorithm used for path-finding and graph traver-
sal. It combines the advantages of both Dijkstra’s algorithm (in that it can find a
shortest path) and Greedy Best-First-Search (in that it can use a heuristic to guide
search). It combines the information that Dijkstra’s algorithm uses (favoring ver-
tices that are close to the starting point) and information that Best-First-Search uses
(favoring vertices that are closer to the goal).
3.1 Theory:
Let g(n) represent the exact cost of the path from the starting point to any vertex n,
and h(n) represent the heuristic estimated cost from vertex n to the goal. Dijkstra’s
algorithms builds a priority queue of nodes ordered on their g(n) values. Best-First-
Search employs a priority queue of nodes ordered on h(n) values. A* balances the
two as it moves from the starting point to the goal. It builds a priority queue of
nodes ordered on f(n) = g(n) + h(n) which is the total estimated path cost through
the node n.
3.2 Code
def A∗−GRAPH−SEARCH ( s t a r t ) :
Let pq be an empty min p r i o r i t y queue
Let c l o s e d be an empty s e t
g( start ) = 0
f ( start ) = h( start )
path ( s t a r t ) = [ ]
pq . push ( s t a r t , f ( s t a r t ) )
9
10 Chapter 3. A* search algorithm
top = pq . pop ( )
i f i s G o a l ( top ) :
r e t u r n f ( top ) , path ( top )
c l o s e d . add ( top )
f o r e a c h next i n succ ( top ) :
i f next not i n c l o s e d :
g ( next ) = g ( top ) + c o s t ( top , next )
f ( next ) = g ( next ) + h ( next )
path ( next ) = path ( top ) . append ( next )
pq . push ( next , f ( next ) )
Lets work through this example. First, S is expanded and nodes A (f(A)=4) and B
(f(B)=3) are pushed onto the queue. Then, B (having smaller f value) is expanded
and G (f(G)=5) is pushed onto the queue. If we declare victory as soon as we push
it onto the queue, we will choose the path S->B->G (having cost 5) and not the
shorter path S->A->G (having cost 4).
Chapter 4
Unification Algorithm
The unification problem in first-order logic can be expressed as follows: Given two
terms containing some variables, find, if it exists, the simplest substitution (i.e., an
assignment of some term to every variable) which makes the two terms equal. The
resulting substitution is called the most general unifier .
4.1 Theory:
Unification is synonymous with pattern-matching, where you combine together
two structures, where variables in one are allowed to match values in the other.
The simplest form of unification happens whenever you call a function in a
normal language. The caller has arguments, and the callee has parameters. The
parameters are "bound to" the arguments, and that produces an instantiation of
the function.
4.2 Code:
The preceding algorithms assumed that we could find the most general unifier of
two atoms. The problem of unification is the following: given two atoms, deter-
mine if they unify, and, if they do, return an MGU of them.
Procedure Unify ( t1 , t 2 )
Inputs
t1 , t 2 : atoms Output
most g e n e r a l u n i f i e r o f t 1 and t 2 i f i t e x i s t s or 0 o t h e r w i s e
Local
E : a s e t of equality statements
S : substitution
E < −{ t 1 = t 2 }
S={}
while ( E ! = { } )
11
12 Chapter 4. Unification Algorithm
5.1 Theory:
The program prompts the user about the order of play, following which are a series
of alternate moves on the user’s and computer’s part until a victory is reached or
the board is full. We make a local copy of the board to assess the outcomes of
different moves, and then choose. We employ a number of techniques to decide
the next move in order of priority:
• A blocking move, if it’s possible for the player to win in their next turn
When executed, the game checks for a victory at every move. Otherwise, it termi-
nates when the board has been filled.
5.2 Code:
import random
def drawBoard ( board ) :
# This f u n c t i o n p r i n t s out t h e board t h a t i t was passed .
# " board " i s a l i s t o f 10 s t r i n g s r e p r e s e n t i n g t h e board ( i g n o r e index
0)
13
14 Chapter 5. Tic Tac Toe
print ( ’ | | ’)
p r i n t ( ’ ’ + board [ 7 ] + ’ | ’ + board [ 8 ] + ’ | ’ + board [ 9 ] )
print ( ’ | | ’)
p r i n t(’−−−−−−−−−−−’)
print ( ’ | | ’)
p r i n t ( ’ ’ + board [ 4 ] + ’ | ’ + board [ 5 ] + ’ | ’ + board [ 6 ] )
print ( ’ | | ’)
p r i n t(’−−−−−−−−−−−’)
print ( ’ | | ’)
p r i n t ( ’ ’ + board [ 1 ] + ’ | ’ + board [ 2 ] + ’ | ’ + board [ 3 ] )
print ( ’ | | ’)
def i n p u t P l a y e r L e t t e r ( ) :
# L e t s t h e p l a y e r type which l e t t e r they want t o be .
# Returns a l i s t with t h e player ’ s l e t t e r as t h e f i r s t item , and t h e
computer ’ s l e t t e r as t h e second .
letter = ’ ’
while not ( l e t t e r == ’X ’ or l e t t e r == ’O’ ) :
p r i n t ( ’ Do you want t o be X or O? ’ )
l e t t e r = input ( ) . upper ( )
def whoGoesFirst ( ) :
# Randomly choose t h e p l a y e r who goes f i r s t .
i f random . r a n d i n t ( 0 , 1 ) == 0 :
r e t u r n ’ computer ’
else :
r e t u r n ’ player ’
def playAgain ( ) :
# This f u n c t i o n r e t u r n s True i f t h e p l a y e r wants t o play again ,
otherwise i t returns False .
p r i n t ( ’ Do you want t o play again ? ( yes or no ) ’ )
r e t u r n input ( ) . lower ( ) . s t a r t s w i t h ( ’ y ’ )
def isWinner ( bo , l e ) :
# Given a board and a player ’ s l e t t e r , t h i s f u n c t i o n r e t u r n s True i f
t h a t p l a y e r has won .
# We use bo i n s t e a d o f board and l e i n s t e a d o f l e t t e r so we don ’ t have
t o type as much .
r e t u r n ( ( bo [ 7 ] == l e and bo [ 8 ] == l e and bo [ 9 ] == l e ) or # a c r o s s t h e
top
5.2. Code: 15
i f i s S p a c e F r e e ( copy , i ) :
makeMove ( copy , computerLetter , i )
i f isWinner ( copy , com pu te rL et te r ) :
return i
# Check i f t h e p l a y e r could win on h i s next move , and b l o c k them .
f o r i i n range ( 1 , 1 0 ) :
copy = getBoardCopy ( board )
i f i s S p a c e F r e e ( copy , i ) :
makeMove ( copy , p l a y e r L e t t e r , i )
i f isWinner ( copy , p l a y e r L e t t e r ) :
return i
# Try t o t a k e one o f t h e c o r n e r s , i f they a r e f r e e .
move = chooseRandomMoveFromList ( board , [ 1 , 3 , 7 , 9 ] )
i f move ! = None :
r e t u r n move
# Try t o t a k e t h e c e n t e r , i f i t i s f r e e .
i f i s S p a c e F r e e ( board , 5 ) :
return 5
# Move on one o f t h e s i d e s .
r e t u r n chooseRandomMoveFromList ( board , [ 2 , 4 , 6 , 8 ] )
def i s B o a r d F u l l ( board ) :
# Return True i f every space on t h e board has been taken . Otherwise
return False .
f o r i i n range ( 1 , 1 0 ) :
i f i s S p a c e F r e e ( board , i ) :
return False
r e t u r n True
p r i n t ( ’ The game i s a t i e ! ’ )
break
else :
turn = ’ computer ’
else :
# Computer ’ s turn .
move = getComputerMove ( theBoard , c om pu te rL ett er )
makeMove ( theBoard , computerLetter , move )
i f isWinner ( theBoard , co mpu te rL et te r ) :
drawBoard ( theBoard )
p r i n t ( ’ The computer has beaten you ! You l o s e . ’ )
gameIsPlaying = F a l s e
else :
i f i s B o a r d F u l l ( theBoard ) :
drawBoard ( theBoard )
p r i n t ( ’ The game i s a t i e ! ’ )
break
else :
turn = ’ player ’
i f not playAgain ( ) :
break