use path probing

main
Harald Holtmann 2025-09-06 08:55:03 +02:00
parent 3f0e979dce
commit 4fdade25dc
1 changed files with 64 additions and 15 deletions

@ -5,6 +5,7 @@ import functools
import json import json
import os.path import os.path
import sys import sys
import random
from collections import defaultdict from collections import defaultdict
@ -15,6 +16,8 @@ class ExploreError(Exception):
@functools.total_ordering @functools.total_ordering
class Path: class Path:
def __init__(self, path=""): def __init__(self, path=""):
if isinstance(path, list):
path = "".join(str(p) for p in path)
self.path = path self.path = path
def __repr__(self): def __repr__(self):
@ -35,8 +38,11 @@ class Path:
def __format__(self, spec): def __format__(self, spec):
return str(self).__format__(spec) return str(self).__format__(spec)
def extend(self, door): def __add__(self, other):
return Path(self.path + str(door)) return Path(self.path + other.path)
def __len__(self):
return len(self.path)
def last(self): def last(self):
return Path(self.path[:-1]), int(self.path[-1]) return Path(self.path[:-1]), int(self.path[-1])
@ -48,9 +54,13 @@ class Path:
return self return self
DOORS = [Path(str(i)) for i in range(6)]
class Explore: class Explore:
def __init__(self, problem): def __init__(self, problem, probes):
self.problem = problem self.problem = problem
self.probes = probes
self.rooms = {} self.rooms = {}
self.room_ids = defaultdict(lambda: set()) self.room_ids = defaultdict(lambda: set())
self.neighbors = {} self.neighbors = {}
@ -58,6 +68,8 @@ class Explore:
self.unification_id = {} self.unification_id = {}
self.unifications = defaultdict(lambda: set()) self.unifications = defaultdict(lambda: set())
self.score = 0
def _path(self, path): def _path(self, path):
return self.unification_id.get(path, path) return self.unification_id.get(path, path)
@ -87,28 +99,36 @@ class Explore:
if path in self.rooms: if path in self.rooms:
return self.rooms[path] return self.rooms[path]
paths = [path.extend(i) for i in range(6)] paths = [path + probe for probe in self.probes]
self.neighbors[path] = [(p, None) for p in paths]
print("explore", paths) print("explore", paths)
results = api.explore([p.path for p in paths])["results"] response = api.explore([p.path for p in paths])
results = response["results"]
self.score = response["queryCount"]
print("id", path, results) print("id", path, results)
label = results[0][-2] self.update(path, [res[len(path) :] for res in results])
neighbors = [r[-1] for r in results]
room_id = str(label) + "".join(str(n) for n in neighbors) def update(self, path, results):
"""
path: path to update
probe: prob result from path.
"""
label = results[0][0]
probe_ids = [r for res in (rs[1:] for rs in results) for r in res]
print(path, results, probe_ids)
room_id = str(label) + "".join(str(p) for p in probe_ids)
self.rooms[path] = room_id self.rooms[path] = room_id
self.room_ids[room_id].add(path) self.room_ids[room_id].add(path)
# update pen-ultimate room self.neighbors[path] = [(path + d, None) for d in DOORS]
# update penultimate room
if path: if path:
pl, dl = path.last() pl, dl = path.last()
p, _ = self.neighbors[pl][dl] p, _ = self.neighbors[pl][dl]
self.neighbors[pl][dl] = (p, room_id) self.neighbors[pl][dl] = (p, room_id)
return room_id
def dump(self): def dump(self):
print(self.problem + " rooms:") print(self.problem + " rooms:")
for r, rid in self.rooms.items(): for r, rid in self.rooms.items():
@ -227,8 +247,36 @@ class Explore:
return api.guess(layout) return api.guess(layout)
def solve(problem): def room_solve(problem):
ex = Explore(problem) ex = Explore(problem, DOORS)
api.select(ex.problem)
ex.explore()
ex.dump()
while True:
unexplored = next(ex.unexplored(), None)
if not unexplored:
break
print("explore", unexplored)
ex.explore(unexplored)
ex.dump()
print("unify")
ex.unify_all()
ex.dump()
print("explored", ex.is_explored())
if ex.is_explored():
print("guess", ex.guess())
print("score", ex.score)
def path_solve(problem, plen):
probe = [Path([random.randrange(6) for _ in range(plen)])]
print("probe path", probe)
ex = Explore(problem, probe)
api.select(ex.problem) api.select(ex.problem)
ex.explore() ex.explore()
ex.dump() ex.dump()
@ -249,6 +297,7 @@ def solve(problem):
print("explored", ex.is_explored()) print("explored", ex.is_explored())
if ex.is_explored(): if ex.is_explored():
print("guess", ex.guess()) print("guess", ex.guess())
print("score", ex.score)
if __name__ == "__main__": if __name__ == "__main__":
@ -264,4 +313,4 @@ if __name__ == "__main__":
if problem not in problems: if problem not in problems:
raise ExploreError(f"unknown problem {problem}") raise ExploreError(f"unknown problem {problem}")
solve(problem) path_solve(problem, int(sys.argv[2]))