-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathState.py
109 lines (83 loc) · 3.5 KB
/
State.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class State:
goal = [1, 2, 3, 4, 5, 6, 7, 8, 0]
#this should be changed manually based on n
#e.g. it should be [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0] if n is 4.
greedy_evaluation = None
AStar_evaluation = None
heuristic = None
def __init__(self, state, parent, direction, depth, cost):
self.state = state
self.parent = parent
self.direction = direction
self.depth = depth
if parent:
self.cost = parent.cost + cost
else:
self.cost = cost
def test(self): #check if the given state is goal
if self.state == self.goal:
return True
return False
#heuristic function based on Manhattan distance
def Manhattan_Distance(self ,n):
self.heuristic = 0
for i in range(1 , n*n):
distance = abs(self.state.index(i) - self.goal.index(i))
#manhattan distance between the current state and goal state
self.heuristic = self.heuristic + distance/n + distance%n
self.greedy_evaluation = self.heuristic
self.AStar_evaluation = self.heuristic + self.cost
return( self.greedy_evaluation, self.AStar_evaluation)
#heuristic function based on number of misplaced tiles
def Misplaced_Tiles(self,n):
counter = 0;
self.heuristic = 0
for i in range(n*n):
for j in range(n*n):
if (self.state[i] != self.goal[j]):
counter += 1
self.heuristic = self.heuristic + counter
self.greedy_evaluation = self.heuristic
self.AStar_evaluation = self.heuristic + self.cost
return( self.greedy_evaluation, self.AStar_evaluation)
@staticmethod
#this would remove illegal moves for a given state
def available_moves(x,n):
moves = ['Left', 'Right', 'Up', 'Down']
if x % n == 0:
moves.remove('Left')
if x % n == n-1:
moves.remove('Right')
if x - n < 0:
moves.remove('Up')
if x + n > n*n - 1:
moves.remove('Down')
return moves
#produces children of a given state
def expand(self , n):
x = self.state.index(0)
moves = self.available_moves(x,n)
children = []
for direction in moves:
temp = self.state.copy()
if direction == 'Left':
temp[x], temp[x - 1] = temp[x - 1], temp[x]
elif direction == 'Right':
temp[x], temp[x + 1] = temp[x + 1], temp[x]
elif direction == 'Up':
temp[x], temp[x - n] = temp[x - n], temp[x]
elif direction == 'Down':
temp[x], temp[x + n] = temp[x + n], temp[x]
children.append(State(temp, self, direction, self.depth + 1, 1)) #depth should be changed as children are produced
return children
#gets the given state and returns it's direction + it's parent's direction till there is no parent
def solution(self):
solution = []
solution.append(self.direction)
path = self
while path.parent != None:
path = path.parent
solution.append(path.direction)
solution = solution[:-1]
solution.reverse()
return solution