172 lines
6.0 KiB
Python
172 lines
6.0 KiB
Python
import heapq
|
||
import time
|
||
|
||
|
||
|
||
def get_percepted_cells(position:tuple):
|
||
cells = []
|
||
for x in range(position[0]- perception_radius, position[0] + perception_radius + 1):
|
||
for y in range(position[1]- perception_radius, position[1] + perception_radius + 1):
|
||
if (x,y) != position:
|
||
cells.append((x,y))
|
||
return cells
|
||
|
||
failed_tests = 0
|
||
passed_tests = 0
|
||
|
||
total_time = 0
|
||
average_time = 0
|
||
|
||
test_number = 0
|
||
with open("20k_testset.txt", "r") as file:
|
||
lines = file.readlines()
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
line_number = 0
|
||
while(test_number < 100):
|
||
#time.sleep(.5)
|
||
start_time = time.time()
|
||
current_test_lines = []
|
||
for local_line_number in range(14):
|
||
current_line = lines[line_number]
|
||
current_test_lines.append(current_line)
|
||
line_number += 1
|
||
|
||
# Initialize cost, heuristic, map, visited nodes, and parent tracking arrays
|
||
min_costs = [[10000]*9 for _ in range(9)] # Initialize minimum cost array with a high value (10000)
|
||
hs = [[0]*9 for _ in range(9)] # Heuristic array for A* (Manhattan distance)
|
||
astar_map = [['.']*9 for _ in range(9)] # Initial unexplored map with '.'
|
||
visited_nodes = [[False]*9 for _ in range(9)] # Track visited nodes
|
||
node_parents = [[None]*9 for _ in range(9)] # Track path parents for backtracking
|
||
|
||
# Input: perception radius and Keymaker position
|
||
perception_radius = int(current_test_lines[1][0]) # 1 or 2 for Neo’s perception variant
|
||
goal_x, goal_y = int(current_test_lines[2][1]), int(current_test_lines[2][4]) # Keymaker’s coordinates
|
||
|
||
# Set up heuristic values (Manhattan distance) and initial costs for A*
|
||
for i in range(9):
|
||
for j in range(9):
|
||
hs[j][i] = abs(j - goal_y) + abs(i - goal_x) # Calculate heuristic distance
|
||
min_costs[j][i] = 10000 # Set initial high cost for all cells
|
||
|
||
min_costs[0][0] = 0 # Starting position (0,0) cost is zero
|
||
|
||
# Priority queue for A* with starting point at (0,0)
|
||
priority_queue = []
|
||
heapq.heappush(priority_queue, (min_costs[0][0] + hs[0][0], 0, 0)) # Push initial cell to queue
|
||
|
||
|
||
|
||
|
||
|
||
|
||
#for line in current_test_lines:
|
||
#print(line[:-1])
|
||
|
||
test_map_matrix = current_test_lines[3:12]
|
||
|
||
#for line in test_map_matrix:
|
||
#print(line[:-1])
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# Main A* loop
|
||
while len(priority_queue) != 0:
|
||
# Extract node with lowest f = g + h value
|
||
temp, current_x, current_y = heapq.heappop(priority_queue)
|
||
if visited_nodes[current_y][current_x]:
|
||
continue
|
||
visited_nodes[current_y][current_x] = True # Mark node as visited
|
||
|
||
# Backtrack to get the path to current node
|
||
parent_node = node_parents[current_y][current_x]
|
||
path_to_current = [(current_x, current_y)]
|
||
while parent_node is not None:
|
||
path_to_current.append(parent_node)
|
||
parent_node = node_parents[parent_node[1]][parent_node[0]]
|
||
|
||
# Execute path, querying for perception data
|
||
for i in reversed(range(len(path_to_current))):
|
||
#print(f"m {path_to_current[i][0]} {path_to_current[i][1]}")
|
||
for x in range(len(test_map_matrix)):
|
||
for y in range(len(test_map_matrix)):
|
||
if (x,y) in get_percepted_cells((current_x, current_y)) and test_map_matrix[x][y] != ".":
|
||
astar_map[x][y] = test_map_matrix[x][y]
|
||
|
||
# Explore neighboring cells
|
||
for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]: # Move in four directions
|
||
neighbor_x = current_x + dx
|
||
neighbor_y = current_y + dy
|
||
# Check boundaries and if cell is unexplored and safe
|
||
if 0 <= neighbor_x < 9 and 0 <= neighbor_y < 9 and not visited_nodes[neighbor_y][neighbor_x] and astar_map[neighbor_y][neighbor_x] not in ('P', 'A', 'S'):
|
||
# Update cost if a better path is found
|
||
if min_costs[neighbor_y][neighbor_x] > min_costs[current_y][current_x] + 1:
|
||
node_parents[neighbor_y][neighbor_x] = (current_x, current_y)
|
||
min_costs[neighbor_y][neighbor_x] = min_costs[current_y][current_x] + 1
|
||
# Add node to priority queue with updated f = g + h value
|
||
heapq.heappush(priority_queue, (min_costs[neighbor_y][neighbor_x] + hs[neighbor_y][neighbor_x], neighbor_x, neighbor_y))
|
||
|
||
# Repeat path execution to keep querying
|
||
for i in range(len(path_to_current)):
|
||
#print(f"m {path_to_current[i][0]} {path_to_current[i][1]}")
|
||
for x in range(len(test_map_matrix)):
|
||
for y in range(len(test_map_matrix)):
|
||
if (x,y) in get_percepted_cells((current_x, current_y)) and test_map_matrix[x][y] != ".":
|
||
astar_map[x][y] = test_map_matrix[x][y]
|
||
|
||
# Check if the goal is reached and output the result
|
||
if min_costs[goal_y][goal_x] != 10000:
|
||
print(f"e {min_costs[goal_y][goal_x]}") # Output shortest path length
|
||
#time.sleep(1)
|
||
passed_tests += 1
|
||
test_number += 1
|
||
end_time = time.time()
|
||
test_time = end_time - start_time
|
||
total_time += test_time
|
||
else:
|
||
print("e -1") # Output -1 if unsolvable.
|
||
#time.sleep(1)
|
||
failed_tests += 1
|
||
test_number += 1
|
||
end_time = time.time()
|
||
test_time = end_time - start_time
|
||
total_time += 0 # we don't consider failed tests in statistics
|
||
|
||
average_time = total_time / passed_tests
|
||
|
||
print("-------A_STAR_RESULTS-------")
|
||
print(f"passed tests: {passed_tests}")
|
||
print(f"failed tests: {failed_tests}")
|
||
print(f"total time: {total_time}")
|
||
print(f"average time: {average_time}")
|
||
'''
|
||
FOR 100 tests
|
||
-------A_STAR_RESULTS-------
|
||
passed tests: 99
|
||
failed tests: 1
|
||
total time: 18.093406677246094
|
||
average time: 0.1827616836085464
|
||
|
||
|
||
FOR 1000 tests
|
||
-------A_STAR_RESULTS-------
|
||
passed tests: 995
|
||
failed tests: 5
|
||
total time: 184.33025455474854
|
||
average time: 0.1852565372409533
|
||
''' |