new A* optimization: worst-case pruning

i'm not sure if this has been described in the literature exactly but it
is similar to existing branch-and-bound techniques.

it doesn't speed up the search directly (the number of visited nodes is
the same) but it does cut the queue length down by an order of magnitude
and shave a couple seconds off of day 16, presumably due to reduced memory
pressure or something.
main
magical 2022-12-17 19:51:23 -08:00
parent e9ada04aa9
commit 910da239c0
2 changed files with 17 additions and 4 deletions

View File

@ -152,6 +152,10 @@ def solve():
m -= 1
return c
def worst2(node):
_, _, min1, min2, closed = node
return min(min1,min2) * pressure(closed)
def is_goal2(node):
_, _, min1, min2, closed = node
return min1 == 0 and min2 == 0 or closed == all_open
@ -209,7 +213,7 @@ def solve():
minutes = 26
start2 = (AA, AA, minutes, minutes, all_closed)
info.clear()
c, _, path = astar.search(start2, is_goal2, neighbors2, heuristic2)
c, _, path = astar.search(start2, is_goal2, neighbors2, heuristic2, worst=worst2)
print(c)
print(max_pressure*minutes - c)

View File

@ -1,6 +1,6 @@
from heapq import heappush, heappop
def search(start, is_goal, neighbors, heuristic=None):
def search(start, is_goal, neighbors, heuristic=None, worst=None):
if heuristic == None:
def heuristic(x):
return 0
@ -16,6 +16,8 @@ def search(start, is_goal, neighbors, heuristic=None):
i += 1
heappush(q, (heuristic(s), i, s, None))
done = {}
if worst:
best_worst = min(worst(s) for s in start)
while q:
z, _, this, prev = heappop(q)
if this in done:
@ -41,8 +43,15 @@ def search(start, is_goal, neighbors, heuristic=None):
c = cost_so_far + c
if n not in done or c < done[n][0]:
h = heuristic(n)
if h is None:
continue
if worst:
if c+h > best_worst:
# if the best possible cost for this node
# is worse than the lowest worst-case cost we've seen
# then don't even bother exploring it
continue
w = worst(n)
if c+w < best_worst:
best_worst = c+w
i += 1
heappush(q, (c+h, i, n, this))