-
Notifications
You must be signed in to change notification settings - Fork 0
/
warehouse_robot.py
237 lines (210 loc) · 7.61 KB
/
warehouse_robot.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# -------------------
# Background Information
#
# In this problem, you will build a planner that helps a robot
# find the shortest way in a warehouse filled with boxes
# that he has to pick up and deliver to a drop zone.
#
# For example:
#
# warehouse = [[ 1, 2, 3],
# [ 0, 0, 0],
# [ 0, 0, 0]]
# dropzone = [2,0]
# todo = [2, 1]
#
# The robot starts at the dropzone.
# The dropzone can be in any free corner of the warehouse map.
# todo is a list of boxes to be picked up and delivered to the dropzone.
#
# Robot can move diagonally, but the cost of a diagonal move is 1.5.
# The cost of moving one step horizontally or vertically is 1.
# So if the dropzone is at [2, 0], the cost to deliver box number 2
# would be 5.
# To pick up a box, the robot has to move into the same cell as the box.
# When the robot picks up a box, that cell becomes passable (marked 0)
# The robot can pick up only one box at a time and once picked up
# it has to return the box to the dropzone by moving onto the dropzone cell.
# Once the robot has stepped on the dropzone, the box is taken away,
# and it is free to continue with its todo list.
# Tasks must be executed in the order that they are given in the todo list.
# You may assume that in all warehouse maps, all boxes are
# reachable from beginning (the robot is not boxed in).
# -------------------
# User Instructions
#
# Design a planner (any kind you like, so long as it works!)
# in a function named plan() that takes as input three parameters:
# warehouse, dropzone, and todo. See parameter info below.
#
# Your function should RETURN the final, accumulated cost to do
# all tasks in the todo list in the given order, which should
# match with our answer. You may include print statements to show
# the optimum path, but that will have no effect on grading.
#
# Your solution must work for a variety of warehouse layouts and
# any length of todo list.
#
# Add your code at line 76.
#
# --------------------
# Parameter Info
#
# warehouse - a grid of values, where 0 means that the cell is passable,
# and a number 1 <= n <= 99 means that box n is located at that cell.
# dropzone - determines the robot's start location and the place to return boxes
# todo - list of tasks, containing box numbers that have to be picked up
#
# --------------------
# Testing
#
# You may use our test function below, solution_check(),
# to test your code for a variety of input parameters.
warehouse = [[1, 2, 3],
[0, 0, 0],
[0, 0, 0]]
dropzone = [2, 0]
todo = [2, 1]
# ------------------------------------------
# plan - Returns cost to take all boxes in the todo list to dropzone
#
# ----------------------------------------
# modify code below
# ----------------------------------------
import math
def search(grid, init, goal, motioncost):
delta = [[-1, 0], # go up
[0, -1], # go left
[1, 0], # go down
[0, 1], # go right
[1, 1], # go upright
[-1, 1], # go upleft
[-1, -1], # go bottomleft
[1, -1], ] # go bottomright
closed = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
closed[init[0]][init[1]] = 1
expand = [[-1 for row in range(len(grid[0]))] for col in range(len(grid))]
x = init[0]
y = init[1]
g = 0
f = g + math.sqrt((init[0] - goal[0]) ** 2 + (init[1] - goal[1]) ** 2)
open = [[f, g, x, y]]
found = False # flag that is set when search is complete
resign = False # flag set if we can't find expand
count = 0
expand[x][y] = count
while not found and not resign:
if len(open) == 0:
resign = True
# return "fail"
else:
open.sort()
open.reverse()
next = open.pop()
g = next[1]
x = next[2]
y = next[3]
expand[x][y] = count
count += 1
if x == goal[0] and y == goal[1]:
found = True
else:
for i in range(len(delta)):
x2 = x + delta[i][0]
y2 = y + delta[i][1]
if x2 >= 0 and x2 < len(grid) and y2 >= 0 and y2 < len(grid[0]):
if closed[x2][y2] == 0 and grid[x2][y2] == 0:
g2 = g + motioncost[i]
f2 = g2 + math.sqrt((x2 - goal[0]) ** 2 + (y2 - goal[1]) ** 2)
open.append([f2, g2, x2, y2])
closed[x2][y2] = 1
return g
def get_index(grid, value):
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == value:
return [i, j]
return 'error, value not found'
def plan(warehouse, dropzone, todo):
cost = 0
motioncost = [1, 1, 1, 1, 1.5, 1.5, 1.5, 1.5]
for i in range(len(todo)):
goal = get_index(warehouse, todo[i])
warehouse[goal[0]][goal[1]] = 0
cost += 2 * search(warehouse, dropzone, goal, motioncost)
return cost
################# TESTING ##################
# ------------------------------------------
# solution check - Checks your plan function using
# data from list called test[]. Uncomment the call
# to solution_check to test your code.
#
def solution_check(test, epsilon=0.00001):
answer_list = []
import time
start = time.clock()
correct_answers = 0
for i in range(len(test[0])):
user_cost = plan(test[0][i], test[1][i], test[2][i])
true_cost = test[3][i]
if abs(user_cost - true_cost) < epsilon:
print
"\nTest case", i + 1, "passed!"
answer_list.append(1)
correct_answers += 1
# print "#############################################"
else:
print
"\nTest case ", i + 1, "unsuccessful. Your answer ", user_cost, "was not within ", epsilon, "of ", true_cost
answer_list.append(0)
runtime = time.clock() - start
if runtime > 1:
print
"Your code is too slow, try to optimize it! Running time was: ", runtime
return False
if correct_answers == len(answer_list):
print
"\nYou passed all test cases!"
return True
else:
print
"\nYou passed", correct_answers, "of", len(answer_list), "test cases. Try to get them all!"
return False
# Testing environment
# Test Case 1
warehouse1 = [[1, 2, 3],
[0, 0, 0],
[0, 0, 0]]
dropzone1 = [2, 0]
todo1 = [2, 1]
true_cost1 = 9
# Test Case 2
warehouse2 = [[1, 2, 3, 4],
[0, 0, 0, 0],
[5, 6, 7, 0],
['x', 0, 0, 8]]
dropzone2 = [3, 0]
todo2 = [2, 5, 1]
true_cost2 = 21
# Test Case 3
warehouse3 = [[1, 2, 3, 4, 5, 6, 7],
[0, 0, 0, 0, 0, 0, 0],
[8, 9, 10, 11, 0, 0, 0],
['x', 0, 0, 0, 0, 0, 12]]
dropzone3 = [3, 0]
todo3 = [5, 10]
true_cost3 = 18
# Test Case 4
warehouse4 = [[1, 17, 5, 18, 9, 19, 13],
[2, 0, 6, 0, 10, 0, 14],
[3, 0, 7, 0, 11, 0, 15],
[4, 0, 8, 0, 12, 0, 16],
[0, 0, 0, 0, 0, 0, 'x']]
dropzone4 = [4, 6]
todo4 = [13, 11, 6, 17]
true_cost4 = 41
testing_suite = [[warehouse1, warehouse2, warehouse3, warehouse4],
[dropzone1, dropzone2, dropzone3, dropzone4],
[todo1, todo2, todo3, todo4],
[true_cost1, true_cost2, true_cost3, true_cost4]]
solution_check(testing_suite) # TRUE