-
Notifications
You must be signed in to change notification settings - Fork 0
/
parameters.py
172 lines (131 loc) · 6.7 KB
/
parameters.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import numpy as np
# ------------------------------------------ Node definition -----------------------------------------
class Node():
# Node initialization
def __init__(self, position):
self.position = position # Tuple (x,y)
self.g = 0 # g-cost
self.h = 0 # h-cost
self.f = None # f-cost
self.parent = None # Parent node
# Print the node
def __str__(self):
return str(self.position)
# Equality of 2 nodes (position)
def __eq__(self, other):
return self.position == other.position
# Less than
def __lt__(self, other):
return self.f < other.f
# Greater than
def __gt__(self, other):
return self.f > other.f
# ---------------------------------------Heuristic functions-------------------------------------------
# Manhattan distance
def manhattan(actual_node, start_node, goal_node, delta):
actualPos = actual_node.position
endPos = goal_node.position
return abs(actualPos[0] - endPos[0]) + abs(actualPos[1] - endPos[1])
# There are many states with the same f-cost, and we have to choose the order in which to expand them.
# For tie_breaking_high_g_cost, we preferred states closer to the goal node than the goal state.
def tie_breaking_high_g_cost(actual_node, start_node, goal_node, delta=0.001):
actualPos = actual_node.position
endPos = goal_node.position
return manhattan(actual_node, start_node, goal_node, delta) * (1 + delta)
# Variance of tie breaking high g-cost, we vary the value of delta in tie_breaking_high_g_cost, according
# to the position of the actual node
def var_tie_breaking_high_g_cost(actual_node, start_node, goal_node, delta=0.001):
actualPos = actual_node.position
endPos = goal_node.position
rate1 = manhattan(actual_node, start_node, goal_node, delta)
rate2 = manhattan(start_node, start_node, goal_node, delta)
return rate1 * (1 + delta * (0.5 + rate1 / rate2))
# There are many states with the same f-cost, and we have to choose the order in which to expand them.
# For tie_breaking_low_g_cost, we preferred states closer to the start node than the goal state.
def tie_breaking_low_g_cost(actual_node, start_node, goal_node, delta=0.001):
actualPos = actual_node.position
endPos = goal_node.position
return manhattan(actual_node, start_node, goal_node, delta) * (1 - delta)
# Variance of tie breaking low g-cost, we vary the value of delta in tie_breaking_low_g_cost, according
# to the position of the actual node
def var_tie_breaking_low_g_cost(actual_node, start_node, goal_node, delta=0.001):
actualPos = actual_node.position
endPos = goal_node.position
rate1 = manhattan(actual_node, start_node, goal_node, delta)
rate2 = manhattan(start_node, start_node, goal_node, delta)
return rate1 * (1 + delta * (1.5 - rate1 / rate2))
# Heuristics dictionary containing all kinds of heuristic functions
heuristics = {
'manhattan': manhattan,
'tie_breaking_high_g_cost': tie_breaking_high_g_cost,
'var_tie_breaking_high_g_cost': var_tie_breaking_high_g_cost,
'tie_breaking_low_g_cost': tie_breaking_low_g_cost,
'var_tie_breaking_low_g_cost': var_tie_breaking_low_g_cost
}
# ----------------------------------------- Finding neighbors ----------------------------------------
# Finding while runing
def next_pos_list(array, actual_node, img_shape, theta):
'''
array: array of height value
actual_node: node object of the actual node that you want to find its neighbors
img_shape: tuple(x_size, y_size) - size of the image
theta: maximum distance of heigh between 2 consecutive positions
'''
res = []
x_size, y_size = img_shape
actualPos = actual_node.position
actual_nodeValue = array[actualPos[0]][actualPos[1]]
# Conditions checking for neighbors
if actualPos[0] + 1 < x_size and abs(actual_nodeValue - array[actualPos[0] + 1][actualPos[1]]) <= theta:
res.append((actualPos[0] + 1, actualPos[1]))
if actualPos[1] + 1 < y_size and abs(actual_nodeValue - array[actualPos[0]][actualPos[1] + 1]) <= theta:
res.append((actualPos[0], actualPos[1] + 1))
if actualPos[0] - 1 >= 0 and abs(actual_nodeValue - array[actualPos[0] - 1][actualPos[1]]) <= theta:
res.append((actualPos[0] - 1, actualPos[1]))
if actualPos[1] - 1 >= 0 and abs(actual_nodeValue - array[actualPos[0]][actualPos[1] - 1]) <= theta:
res.append((actualPos[0], actualPos[1] - 1))
return res
# Find neighbors first before run
def make_grid(array, img_shape, theta):
'''
array: array of height value
img_shape: tuple(x_size, y_size) - size of the image
theta: maximum distance of heigh between 2 consecutive positions
'''
grid = [[None for j in range(len(array))] for i in range(len(array))]
x_size, y_size = img_shape
for i in range(len(array)):
for j in range(len(array)):
res = []
actual_nodeValue = int(array[i][j])
# Conditions checking for neighbors
if i + 1 < x_size and abs(actual_nodeValue - int(array[i + 1][j])) <= theta:
res.append((i + 1, j))
if j + 1 < y_size and abs(actual_nodeValue - int(array[i][j + 1])) <= theta:
res.append((i, j + 1))
if i - 1 >= 0 and abs(actual_nodeValue - int(array[i - 1][j])) <= theta:
res.append((i - 1, j))
if j - 1 >= 0 and abs(actual_nodeValue - int(array[i][j - 1])) <= theta:
res.append((i, j - 1))
# grid[i][j] contains a list of points which can be the neighbors of the point at position (i,j)
grid[i][j] = res
return grid
# ----------------------------------------- Data initialization ----------------------------------------
# Random the position of node
def init(size):
start_node = (np.random.randint(0, size), np.random.randint(0, size))
goal_node = (np.random.randint(0, size), np.random.randint(0, size))
return start_node, goal_node
# Create a list of n pairs of nodes
def random_initialization(n, size):
return [init(size) for i in range(n)]
# -------------------------------------- Analysis initialization -------------------------------------
# Define the class containing our analysis results
class AnalysisResults:
def __init__(self, size):
self.size = size # Size of image
# Dictionary of average run time and average steps_count, for example:
# avg_run_time[(0,0.5)] returns the average run time of image inside the
# bin of standard deviation from 0 to 0.5
self.avg_run_time = {}
self.avg_steps_count = {}