Skip to content

ctde_v0.run_skills_overnight

run_skills_overnight

Overnight SKILLS+SELECTOR batch launcher — the SuperBlue role-selector arms.

Launches, on the FIXED honest spec — comm_r = 5 every rung, hard collision-mask on, soft/learned connectivity (no guardrail), frontier-attn explorer, 100-step horizon — the skill/selector arms across TWO experiment shapes, --seeds seeds each. Everything is graded on the metrics the trainer logs every iter: coverage, the REAL connectivity bar (λ₂>0.5) alongside the trivial one, behavioural diversity (SND) and role-distinctness.

base : the homogeneous shared explorer, no extra flags. The REFERENCE, and the single-Actor BOOTSTRAP the ladder warm-starts from at each rung. role : the hardcoded explorer/relay baseline (--role-picker expl_relay) — the "roles by hand" control the learned selector has to beat. sel_scr_off : selector on, scripted flock, congestion off (--selector on --flock scripted --congestion off). sel_scr_on : selector on, scripted flock, congestion on. sel_lrn_off : selector on, learned flock, congestion off. sel_lrn_on : selector on, learned flock, congestion on.

The 2×2 selector sweep crosses {scripted, learned} flock × {off, on} congestion, asking whether a LEARNED role-selector (and a learned vs scripted flock, with/without a congestion signal) divides labour better than the hand-coded role split.

TWO experiment shapes, BOTH at horizon 100 / comm_r 5: 1. density-pinned LADDER 16x4 -> 24x6 -> 32x10: for base/role + the 4 selector arms, rung i warm-starts rung i-1 (--init-from prev model.eqx + a needs dep on it). Run-dirs /seed{S}/ladder/{arm}/{g}x{g}x{n}. 2. fixed-world N-SWEEP grid 24, comm_r 5, N in {4,6,9,12}: for base + the 4 selector arms (role SKIPPED here), each trained FRESH (no warm-start, no deps) — "do more agents divide labour or just flood?" at a fixed world + fixed 100-step budget. Run-dirs /seed{S}/nsweep/{arm}/24x24x{n}.

DEPENDENCY-AWARE + RESUMABLE: each run is a unit whose run-dir is skipped once it holds a model.eqx; a ladder unit launches only once its needs predecessor's ckpt exists (rung i-1 -> rung i within an arm's ladder); N-sweep units are fresh and depend on nothing. --jobs N runs up to N train_ctde subprocesses at once — balthar is MEMORY-BOUND (~3 concurrent @32²/10, ~6 @24²/6), so keep N small at the top rung. --dry-run prints the full plan + deps and launches nothing.

# see the whole plan first (no training):
JAX_PLATFORMS=cpu PYTHONPATH=.:../../../FiedlerValueEstimation     /Users/bijanmehr/Project.Zymera/zymera_lab/.venv/bin/python         ctde_v0/run_skills_overnight.py --dry-run

# the real overnight batch on balthar (drop JAX_PLATFORMS so it uses the GPU), 2 at a time:
PYTHONPATH=.:../../../FiedlerValueEstimation ~/ZymeraLab/.venv/bin/python         ctde_v0/run_skills_overnight.py --out runs/skills --seeds 3 --iters 1500         --rollouts 16 --jobs 2

===>>> This launcher LAUNCHES REAL TRAINING; run it deliberately. <<<===

Unit

Unit(uid, run_dir, rung, seed, extra, init_from_dir, needs_dir)

One train_ctde run: an id, its run-dir, the extra flags, the seed/rung, and the run-dir of a predecessor whose model.eqx must exist before it can start (or None).

Source code in experiments/ctde_v0/run_skills_overnight.py
106
107
108
109
110
111
112
113
114
def __init__(self, uid, run_dir, rung, seed, extra, init_from_dir, needs_dir):
    self.uid = uid
    self.run_dir = run_dir
    self.rung = rung                     # (g, n, r)
    self.seed = seed
    self.extra = extra
    self.init_from_dir = init_from_dir   # run-dir whose model.eqx warm-starts this, or None
    self.needs_dir = needs_dir           # run-dir that must be done first, or None
    self.proc = None