mark_solver

main
Harald Holtmann 2025-09-07 00:50:05 +02:00
parent 6b7a2d3da5
commit 5bb035c73a
3 changed files with 133 additions and 21 deletions

@ -30,13 +30,18 @@ def select(problem: str):
return response.json()["problemName"]
explore_cache = {"seed": random.getrandbits(30)}
try:
with open("explore_cache.json") as h:
explore_cache = json.loads(h.read())
except OSError:
pass
random.seed(explore_cache["seed"])
explore_cache = {}
def init_explore_cache():
global explore_cache
explore_cache = {"seed": random.getrandbits(30)}
try:
with open("explore_cache.json") as h:
explore_cache = json.loads(h.read())
except OSError:
pass
random.seed(explore_cache["seed"])
def write_explore_cache():
@ -51,6 +56,9 @@ def clean_explore_cache():
pass
init_explore_cache()
def explore(plans: List[str]):
cache_key = ",".join(plans)
if cache_key in explore_cache:

@ -87,11 +87,14 @@ class Explore:
return path
def explore(self, path=Path(), probes=None):
def explore(self, path=Path(), probes=None, mark=Path()):
probes = probes or self.probes
path = self._path(path)
paths = [path + probe for probe in probes]
paths = [mark + path + probe for probe in probes]
num_marks = mark.path.count("[")
prefix_len = len(mark) - 2 * num_marks + len(path)
print("explore", paths)
response = api.explore([p.path for p in paths])
@ -99,7 +102,7 @@ class Explore:
self.score = response["queryCount"]
print("id", path, results)
return [res[len(path) :] for res in results]
return [res[prefix_len:] for res in results]
def _add_room(self, path, results):
label = results[0][0]
@ -161,9 +164,9 @@ class Explore:
for r, rid in self.rooms.items():
print(f" {r:<10}: {rid} {self.neighbors[r]}")
print()
for rid, paths in self.room_ids.items():
print(f" {rid}: {paths}")
print()
# for rid, paths in self.room_ids.items():
# print(f" {rid}: {paths}")
# print()
# for p, pu in self.unification_id.items():
# print(f" {p}: {pu}")
@ -262,7 +265,7 @@ class Explore:
len(p) == 1 for p in self.room_ids.values()
)
def guess(self):
def guess(self, orig=None):
aedi = graph.Aedificium(self.problem)
ids = {}
@ -302,23 +305,45 @@ class Explore:
)
aedi.add_edge(src[0], src[1], trg[0], trg[1])
if orig:
rooms = orig
else:
rooms = {}
for path, rid in self.rooms.items():
rooms[path] = rid[0]
layout = {
"rooms": [int(self.rooms[p][0]) for p in ids.keys()],
"rooms": [int(rooms[p]) for p in ids.keys()],
"startingRoom": ids[Path()],
"connections": connections,
}
# print(layout)
aedi.render()
return api.guess(layout)
def returnfrom(self, path):
queue = [(path, Path())]
while queue:
p, ret = queue.pop(0)
if p == Path():
return ret
for d, (q, _) in enumerate(self.neighbors[p]):
queue.append((q, Path([d])))
assert False, "return path not found"
def walk(self, path):
here = Path()
for d in map(int, path.path):
here = self.neighbors[here][d][0]
return here
def room_solve(problem, nrooms, plen):
ex = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
print(ex.probes)
api.select(ex.problem)
res = ex.explore(Path())
ex.update(Path(), res)
ex.dump()
@ -342,6 +367,77 @@ def room_solve(problem, nrooms, plen):
print("score", ex.score)
def get_mark(rid):
return Path("[" + str(int(rid[0]) ^ 3) + "]")
def mark_solve(problem, nrooms, plen):
ex0 = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
api.select(ex0.problem)
res = ex0.explore(Path())
ex0.update(Path(), res)
ex0.dump()
while True:
door, unexplored = next(ex0.unexplored(), (None, None))
if unexplored is None:
break
print("explore", door, unexplored)
path = unexplored + Path([door])
res = ex0.explore(path)
ex0.update(path, res)
ex0.dump()
ex0.unify_all()
ex0.dump()
print("found all rooms")
mark = Path()
for p, rid in ex0.rooms.items():
q = ex0.returnfrom(p)
mark = mark + p + get_mark(rid) + q
print("marked", mark)
ex1 = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
res = ex1.explore(Path(), mark=mark)
ex1.update(Path(), res)
ex1.dump()
while True:
door, unexplored = next(ex1.unexplored(), (None, None))
if unexplored is None:
break
print("explore", door, unexplored)
path = unexplored + Path([door])
res = ex1.explore(path, mark=mark)
ex1.update(path, res)
ex1.dump()
ex1.unify_all()
ex1.dump()
print("explored", ex1.is_explored())
if ex1.is_explored():
# get old markings
orig = {}
for path in ex1.rooms.keys():
p = ex0.walk(path)
rid = ex0.rooms[p]
orig[path] = rid[0]
print(path, p, rid)
ex0.dump()
ex1.dump()
print(orig)
print("guess", ex1.guess(orig=orig))
print("score", ex0.score + ex1.score)
assert False
def path_solve(problem, nrooms, plen):
maxlen = 18 * nrooms
probe = Path([random.randrange(6) for _ in range(plen)])
@ -402,13 +498,19 @@ if __name__ == "__main__":
with open(os.path.join("..", "problems.json")) as h:
problems = json.loads(h.read())
problems = {p["problem"]: {"size": p["size"]} for p in problems}
problems = {
p["problem"]: {"size": p["size"], "idx": i} for i, p in enumerate(problems)
}
if problem not in problems:
raise ExploreError(f"unknown problem {problem}")
try:
room_solve(problem, problems[problem]["size"], int(sys.argv[2]))
if problems[problem]["idx"] < 6:
room_solve(problem, problems[problem]["size"], int(sys.argv[2]))
else:
mark_solve(problem, problems[problem]["size"], int(sys.argv[2]))
api.clean_explore_cache()
# except ExploreError as exc:
# api.clean_explore_cache()

@ -12,7 +12,9 @@ class Aedificium:
def add_edge(self, scr, src_d, trg, trg_d):
self.graph.add_edge(
pydot.Edge(scr, trg) #, headport=self.PORTS[src_d], tailport=self.PORTS[trg_d])
pydot.Edge(
scr, trg
) # , headport=self.PORTS[src_d], tailport=self.PORTS[trg_d])
)
def render(self):