Source command megaminx tpu merge
Skill Erlemar/cayley-puzzles/.agents/skills/source-command-megaminx-tpu-merge
Neural distance heuristics + GPU/TPU beam search for the CayleyPy IHES Picture Cube and Megaminx puzzles
npx -y skills add Erlemar/cayley-puzzles --skill source-command-megaminx-tpu-mergeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Pull the latest cayleypy-tpu-beam-smoke kernel output, aggregate per-rank JSONs, merge with current best, verify, and prep for submission.
SKILL.md
6.3 KB, as published. Nobody here has run it
source-command-megaminx-tpu-merge
Use this skill when the user asks to run the migrated source command megaminx-tpu-merge.
Command Template
/megaminx-tpu-merge
Bundles the recurring TPU post-completion ritual we run after every kernel finishes (or hits Kaggle's ~9h kill). Used 5+ times across v15 → v19a-fix.
Usage
/megaminx-tpu-merge <out_name>— pulls Kaggle output, aggregates ranks, merges with current best, writesmegaminx/submissions/<out_name>.csv./megaminx-tpu-merge merge_tpu_v19b— typical use after v19b kernel./megaminx-tpu-merge merge_tpu_v19b base=megaminx/submissions/...csv— explicit base CSV.
Defaults
- Kernel slug:
artgor/cayleypy-tpu-beam-smoke. - Working dir:
C:\Users\<user>\AppData\Local\Temp\<out_name>. - Base: latest
merge_*.csvinmegaminx/submissions/(smallest move count). - Output:
megaminx/submissions/<out_name>.csv. - Standalone (TPU-only) output:
megaminx/submissions/<out_name>_standalone.csv.
Execution
1. Pull kernel output
export KAGGLE_API_TOKEN=$KAGGLE_API_TOKEN PYTHONUTF8=1 PYTHONIOENCODING=utf-8
mkdir -p /tmp/<out_name>
.venv/Scripts/kaggle.exe kernels output artgor/cayleypy-tpu-beam-smoke -p /tmp/<out_name> 2>&1 | tail -3
If KernelWorkerStatus.RUNNING: ABORT — kernel hasn't finished yet.
2. Aggregate per-rank JSONs + map to move names
NOTE: MINGW /tmp/<dir> maps to C:\Users\<user>\AppData\Local\Temp\<dir> —
Python on Windows needs the Windows-native path.
PYTHONUTF8=1 .venv/Scripts/python.exe -c "
import json, glob, csv, sys
sys.path.insert(0, 'megaminx/src'); sys.path.insert(0, 'src')
from megaminx.puzzle import Megaminx
puz = Megaminx.load('megaminx/data/puzzle_info.json')
MOVE_NAMES = list(puz.move_names)
base = r'C:\Users\<user>\AppData\Local\Temp\<out_name>'
records = []
for path in sorted(glob.glob(base + r'\rank_*_final.json')) + sorted(glob.glob(base + r'\rank_*_partial.json')):
with open(path) as f:
records.extend(json.load(f))
# Dedupe (final supersedes partial; same data anyway)
seen = set(); unique = []
for r in records:
key = (r['pid'], r['rot_idx'])
if key in seen: continue
seen.add(key); unique.append(r)
# Group by pid, take min over verified rotations
by_pid = {}
for r in unique:
if not r.get('verify_ok'): continue
by_pid.setdefault(r['pid'], []).append(r)
print(f'records: {len(unique)} pids covered: {len(by_pid)}')
best_per_pid = {pid: min(recs, key=lambda r: r['path_len'])['path_idx_orig']
for pid, recs in by_pid.items()}
# Write standalone TPU CSV
with open('megaminx/submissions/<out_name>_standalone.csv', 'w', newline='') as f:
w = csv.writer(f); w.writerow(['initial_state_id', 'path'])
for pid in range(1001):
if pid in best_per_pid:
names = [MOVE_NAMES[m] for m in best_per_pid[pid]]
w.writerow([pid, '.'.join(names)])
else:
w.writerow([pid, ''])
print(f'wrote standalone CSV')
"
Report: total records, pids covered, distribution of rotations-per-pid (helps sanity check that K coverage is reasonable).
3. Merge with current best
PYTHONUTF8=1 .venv/Scripts/python.exe -c "
import csv
from collections import Counter
def load_paths(p):
return {int(r['initial_state_id']): r['path'].split('.') if r['path'] else []
for r in csv.DictReader(open(p))}
best = load_paths('<base>')
tpu = load_paths('megaminx/submissions/<out_name>_standalone.csv')
bucket_wins = Counter(); bucket_savings = Counter()
wins = 0; total_savings = 0
for pid in range(1001):
bp = best.get(pid, [])
tp = tpu.get(pid, [])
if tp and len(tp) < len(bp):
wins += 1; total_savings += len(bp) - len(tp)
bucket_wins[pid // 100] += 1
bucket_savings[pid // 100] += len(bp) - len(tp)
base_total = sum(len(v) for v in best.values())
print(f'current best: {base_total} moves')
print(f'TPU wins: {wins} pids, saved {total_savings} moves')
print()
print('per-bucket wins:')
for b in sorted(bucket_wins.keys()):
print(f' bucket {b}: {bucket_wins[b]:3} wins, {bucket_savings[b]:5} saved')
with open('megaminx/submissions/<out_name>.csv', 'w', newline='') as f:
w = csv.writer(f); w.writerow(['initial_state_id', 'path'])
for pid in range(1001):
bp = best.get(pid, [])
tp = tpu.get(pid, [])
chosen = tp if (tp and len(tp) < len(bp)) else bp
w.writerow([pid, '.'.join(chosen)])
print(f'wrote merge CSV (delta -{total_savings})')
"
4. Verify merged
PYTHONUTF8=1 .venv/Scripts/python.exe -c "
import sys
sys.path.insert(0, 'megaminx/src'); sys.path.insert(0, 'src')
from megaminx.puzzle import Megaminx
from cayley.verify import verify_submission
from pathlib import Path
puz = Megaminx.load(Path('megaminx/data/puzzle_info.json'))
r = verify_submission(puz, Path('megaminx/data/test.csv'),
Path('megaminx/submissions/<out_name>.csv'))
print(f'verify: {r.n_valid}/{r.n_total} valid, total {r.total_moves:,}')
sys.exit(0 if r.all_valid else 1)
"
Anything other than 1001/1001 valid: STOP. Investigate before submitting.
5. Report and suggest next step
Print:
TPU merge ready: megaminx/submissions/<out_name>.csv = <new_total> (delta -<savings> vs <base_total>)
Suggested next: /megaminx-submit <out_name>.csv "<description>"
DO NOT submit automatically.
Gotchas
- Windows path conversion: MINGW
/tmp/foo≠ WindowsC:\Users\...\Temp\foo. Use Python on the Windows path explicitly.cygpath -w /tmp/fooworks. - Empty path rows in standalone CSV are expected for pids the kernel didn't reach. The merge with current best fills them in.
- Partial pids (fewer than K rotations completed) are still useful — take min over what's available. Often 3/4 rotations is enough.
verify_ok=Falserotations happen rarely; the conjugation-translated path failed CPU verification. Skip those when taking min; other rotations cover the pid.
Cost reference
Aggregation + merge typically takes 30s-2min depending on JSON size:
| kernel size | aggregate | merge |
|---|---|---|
| 5 pids smoke | ~2s | ~1s |
| 500 pids partial | ~30s | ~5s |
| 1001 pids full | ~1min | ~10s |