zymera.missions
missions
Missions — reward as data, plus group routing for the adversarial roadmap.
A :class:Mission is a frozen composition of :class:RewardTerm\ s: the env
asks it for reward (Σ weighted terms + the UNWEIGHTED per-term dict that
feeds info["reward_terms"]), done, mission-owned metrics, and
drawable annotations. :class:GroupedMission routes per-group missions
over a shared :class:~zymera.metrics.StepCtx so k-of-N red agents can score
a different objective than the blue team (design spec §3.1).
JAX contract (the static-object rule):
- Missions and terms are frozen, hashable, closure-captured trace-time constants. Term SET is static; weights may become traced later — never gate on a weight's value (doctrine #3).
init_state/updatemust keep an IDENTICAL pytree structure between reset and every step (doctrine #6). The default mission state is().donegating onmax_stepsis Python-time (static config), never on traced data.
Sign convention: term functions return UNSIGNED magnitudes; penalties get
their sign from the :class:RewardTerm weight (v0 subtracted
w_coll * collisions — here the default collision term carries -4.0).
RewardTerm
dataclass
RewardTerm(name, weight, fn, requires=frozenset())
One named reward component: weight · fn(prev, world, action, ctx).
requires names the :class:~zymera.metrics.StepCtx fields the term
reads — the env unions these across terms/obs at __init__ so only the
requested machinery compiles. fn must return the UNWEIGHTED (N,)
value; the weighted sum happens in :meth:Mission.reward.
Point
dataclass
Point(pos, tag='')
A marked cell — VIP, intruder, rally point. pos is (2,) (row, col).
Path
dataclass
Path(cells, tag='')
An ordered cell sequence — patrol route, planned path. cells is (K, 2).
Region
dataclass
Region(mask, tag='')
A cell mask — jammed zone, goal area. mask is (H, W) bool.
Mission
dataclass
Mission(terms=(), max_steps=None)
A reward-term bundle with the full mission protocol surface.
Defaults: () mission state, identity update, timeout-only done
(all-False when max_steps is None), sum-of-weighted-terms reward
returning the unweighted per-term dict.
requires
property
requires
Union of the terms' StepCtx requirements.
init_state
init_state(key, world)
Mission-owned pytree at reset. Default: () (uses no key).
Source code in zymera/missions.py
139 140 141 142 | |
update
update(prev, world, ctx, mstate, key)
Advance mission-owned state (scripted NPCs, waypoints). Default: identity — MUST preserve pytree structure (doctrine #6).
Source code in zymera/missions.py
144 145 146 147 148 | |
done
done(world, ctx, mstate)
(N,) bool. All-False, or step_count >= max_steps broadcast when
max_steps is set (Python-time gate on static config).
Source code in zymera/missions.py
150 151 152 153 154 155 156 157 | |
reward
reward(prev, world, action, ctx, mstate)
(Σ wᵢ·termᵢ (N,) f32, {name: UNWEIGHTED (N,) f32}).
The unweighted dict feeds info["reward_terms"] so analysis can
re-weight post-hoc without re-running.
Source code in zymera/missions.py
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
metrics
metrics(world, ctx, mstate)
Mission-owned success metrics: team coverage fraction, plus the
giant-component fraction when the ctx carries reach (Python-time
gate — ctx structure is a function of env config only).
Source code in zymera/missions.py
178 179 180 181 182 183 184 185 186 187 188 | |
annotations
annotations(world, mstate)
Drawable primitives for zymera.viz. Default: none.
Source code in zymera/missions.py
190 191 192 193 | |
Assignment
Bases: Protocol
Reset-time group-id assignment: assign(key, n_agents) -> (N,) int32.
FixedAssignment
dataclass
FixedAssignment(groups=None)
Deterministic group ids. groups=None → everyone in group 0.
Ignores its key.
RandomKofN
dataclass
RandomKofN(k, group=1)
A random k-subset of agents gets group (default 1); the rest stay 0.
Membership re-randomizes per reset WITHOUT retracing — the draw is pure JAX on the reset key (the red-within-blue graft, spec §3.1).
GroupedMission
dataclass
GroupedMission(assignment, missions)
Per-group objectives over a shared world: missions[g] scores the
agents with world.group == g.
Fixed-shape routing: every group-mission's reward/done is computed over
ALL N agents, then where-selected by group id — no dynamic shapes, no
retrace when :class:RandomKofN re-rolls membership. Per-term/metric
names are namespaced g{i}/<name>. Agents whose group id has no
mission (out of range) score 0 and never finish — keep ids in range.
NOTE (judge-panel mandate): the StepCtx is SHARED across groups — coverage counts every agent's footprint and connectivity reads the union graph. Per-group ctx semantics (e.g. blue-only coverage) must be decided explicitly per term when red training lands.
requires
property
requires
Union of all group-missions' StepCtx requirements.
terms
property
terms
All groups' terms, names namespaced g{i}/<name> (protocol
compatibility; uniqueness holds when each sub-mission's does).
done
done(world, ctx, mstate)
(N,) bool — each agent reports its OWN group's mission done.
Source code in zymera/missions.py
321 322 323 324 325 326 | |
reward
reward(prev, world, action, ctx, mstate)
Each group-mission's total is computed over ALL N (fixed shape),
then routed by where(group == g, ...) and summed. The per-term
dict keeps the UNMASKED unweighted values under g{i}/<name> —
mask post-hoc with world.group in analysis.
Source code in zymera/missions.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |