| """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() |
|
|