Sudoku_superposition / code /level_instance_stats.py
Avra98's picture
Add README and training/generation code
bb23b91 verified
Raw
History Blame Contribute Delete
3.52 kB
"""Candidate-set size and instance count per stage, level 3 vs level 8.
Two metrics only, measured on the training masks.
"""
import argparse
import multiprocessing as mp
import numpy as np
import superposition_instances as SI
_MASKS = None
_ARGS = None
def _init(path, args):
global _MASKS, _ARGS
_MASKS = np.load(path, mmap_mode="r")
_ARGS = args
def _one(idx):
out = []
for s in range(_MASKS.shape[1]):
mask = np.array(_MASKS[idx, s]).astype(np.uint16)
_, empties = SI.split_cells(mask)
sizes = [len(SI.digits_of(mask[c])) for c in empties]
width = float(np.mean(sizes)) if sizes else 1.0
wmax = int(np.max(sizes)) if sizes else 1
r = SI.instances_for_stage(
mask, max_confine=_ARGS.max_confine,
max_instances=_ARGS.max_instances,
max_attempts=_ARGS.max_attempts, seed=idx * 100 + s,
max_repair=_ARGS.max_repair)
out.append((s, width, wmax, r["n_instances"], len(empties)))
return out
def run(level, args):
meta = np.load(args.meta)
idxs = np.where(meta[:, 1] == level)[0][:args.limit].tolist()
with mp.Pool(args.workers, initializer=_init,
initargs=(args.masks, args)) as pool:
res = pool.map(_one, idxs, chunksize=4)
widths, maxes, counts, opens = {}, {}, {}, {}
for rows in res:
for s, w, wm, n, ne in rows:
widths.setdefault(s, []).append(w)
maxes.setdefault(s, []).append(wm)
counts.setdefault(s, []).append(n)
opens.setdefault(s, []).append(ne)
return len(idxs), widths, maxes, counts, opens
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--masks", default="datasets_multicandidate_s12/train_cand_masks.npy")
ap.add_argument("--meta", default="datasets_multicandidate_s12/train_meta.npy")
ap.add_argument("--limit", type=int, default=400)
ap.add_argument("--max-confine", type=int, default=1)
ap.add_argument("--max-instances", type=int, default=64)
ap.add_argument("--max-attempts", type=int, default=300)
ap.add_argument("--max-repair", type=int, default=120)
ap.add_argument("--workers", type=int, default=60)
args = ap.parse_args()
n3, w3, m3, c3, o3 = run(3, args)
n8, w8, m8, c8, o8 = run(8, args)
print(f"training masks, {n3} level-3 puzzles and {n8} level-8 puzzles")
print(f"confinement threshold |S| <= {args.max_confine}")
print()
print(f"{'':>5} {'------------- level 3 -------------':>42} "
f"{'------------- level 8 -------------':>42}")
print(f"{'stage':>5} {'mean':>7} {'max':>7} {'worst':>7} {'open':>7} "
f"{'inst':>7} {'mean':>7} {'max':>7} {'worst':>7} {'open':>7} {'inst':>7}")
print("-" * 96)
for s in sorted(w3):
print(f"{s:>5} "
f"{np.mean(w3[s]):>7.2f} {np.mean(m3[s]):>7.2f} "
f"{np.max(m3[s]):>7d} {np.mean(o3[s]):>7.1f} "
f"{np.mean(c3[s]):>7.1f} "
f"{np.mean(w8[s]):>7.2f} {np.mean(m8[s]):>7.2f} "
f"{np.max(m8[s]):>7d} {np.mean(o8[s]):>7.1f} "
f"{np.mean(c8[s]):>7.1f}")
print()
print("mean = mean candidate set size over undetermined cells")
print("max = mean over puzzles of the largest candidate set in that puzzle")
print("worst = largest candidate set seen in any puzzle at that stage")
print("open = undetermined cells remaining; inst = instances at saturation")
if __name__ == "__main__":
main()