-
Notifications
You must be signed in to change notification settings - Fork 18
/
node.py
99 lines (86 loc) · 2.71 KB
/
node.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
'''
Code developed by Ricardo Soares
------------------------------
University of Aberdeen
MSc Artificial Intelligence
Written in Python 2.7.14
'''
from Queue import Queue
from copy import deepcopy
'''
Instantiates the node. Only the passing argument
"puzzle" is necessary for the creating of a Node.
So, we've given the other two values a default value.
'''
class Node:
def __init__(self, puzzle, parent=None, move=""):
self.state = puzzle
self.parent = parent
self.depth = 0
if parent is None:
self.depth = 0
self.moves = move
else:
self.depth = parent.depth+1
self.moves = parent.moves + move
'''
Checks if the Node's state is a goal state.
'''
def goalState(self):
return self.state.checkPuzzle()
'''
Generates the node's children states.
'''
def succ(self):
succs = Queue()
for m in self.state.moves:
p = deepcopy(self.state)
p.doMove(m)
if p.zero is not self.state.zero:
succs.put(Node(p, self, m))
return succs
'''
Chooses between the two available heuristics
'''
def costHeur(self, heuristic):
return self.nWrongTiles() if heuristic is 0 else self.manhattanDistance()
'''
First heuristic - number of wrong tiles
Every time there's a tile in the wrong place, we
add 1 to the result. Heavily inspired in the
puzzle.checkPuzzle() loop.
'''
def nWrongTiles(self):
result = 0
count = 1
for i in range(0,self.state.size):
for j in range(0,self.state.size):
if self.state.puzzle[i][j]!=(count%(self.state.size*self.state.size)):
result += 1
count+=1
return result
'''
Second heuristic - distance of wrong tiles to their
right position. After a little bit of scheming, came
the mathematical conclusion that:
x = n-1 %3
y = n-1 /3
which concluded into the following result.
'''
def manhattanDistance(self):
result = 0
count = 1
for i in range(0,self.state.size):
for j in range(0,self.state.size):
index = self.state.puzzle[i][j] - 1
distance = (2-i)+(2-j) if index == -1 else abs(i-(index/self.state.size))+abs(j-(index%self.state.size))
result += distance
count+=1
return result
'''
When printing the node, we obtain the moves from the
starting state to this specific one.
'''
def __str__(self):
return str(self.moves)
#Works!