Files
TheMatrixUniverse/main_A_star_testing.py
2024-11-02 00:09:48 +03:00

172 lines
6.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 Neos perception variant
goal_x, goal_y = int(current_test_lines[2][1]), int(current_test_lines[2][4]) # Keymakers 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
'''