Skip to content

Commit 8fff19c

Browse files
authored
Add JaxARC environment setup and documentation (#188)
1 parent 807edfa commit 8fff19c

8 files changed

Lines changed: 215 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Stoix currently offers the following building blocks for Single-Agent RL researc
9595
### Environment Wrappers 🍬
9696
Stoix offers wrappers for:
9797

98-
- **JAX environments:** [Gymnax][gymnax], [Jumanji][jumanji], [Brax][brax], [XMinigrid][xminigrid], [Craftax][craftax], [POPJym][popjym], [Navix][navix] and more.
98+
- **JAX environments:** [Gymnax][gymnax], [Jumanji][jumanji], [Brax][brax], [XMinigrid][xminigrid], [Craftax][craftax], [POPJym][popjym], [Navix][navix], [JaxARC][jaxarc] and more.
9999
- **Non-JAX environments:** [Envpool][envpool] and [Gymnasium][gymnasium].
100100

101101
### Statistically Robust Evaluation 🧪
@@ -270,3 +270,4 @@ We would like to thank the authors and developers of [Mava][mava] as this was es
270270
[envpool]: https://github.com/sail-sg/envpool/
271271
[gymnasium]: https://github.com/Farama-Foundation/Gymnasium
272272
[cleanba]: https://github.com/vwxyzjn/cleanba
273+
[jaxarc]: https://github.com/aadimator/JaxARC

docs/envs/jaxarc.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# JaxARC
2+
3+
[JaxARC](https://github.com/aadimator/JaxARC) is a hardware-accelerated ARC (Abstraction and Reasoning Corpus) environment built on JAX. It enables massively parallel RL training on ARC puzzle tasks with full JIT compilation support.
4+
5+
## Basic Usage
6+
7+
To run PPO with JaxARC on the MiniARC dataset:
8+
9+
```bash
10+
python stoix/systems/ppo/anakin/ff_ppo.py env=jaxarc/default
11+
```
12+
13+
This uses the `Mini` dataset (70 tasks) with point-based actions — a good starting point for prototyping.
14+
15+
To train on the full ARC-AGI-1 training set (400 tasks):
16+
17+
```bash
18+
python stoix/systems/ppo/anakin/ff_ppo.py env=jaxarc/agi1_train
19+
```
20+
21+
## Available Configs
22+
23+
| Config | Dataset | Tasks | Action Mode | Description |
24+
|--------|---------|-------|-------------|-------------|
25+
| `jaxarc/default` | MiniARC | 70 | point | Small dataset for fast prototyping |
26+
| `jaxarc/agi1_train` | ARC-AGI-1 | 400 | point | Official ARC training benchmark |
27+
| `jaxarc/agi1_bbox` | ARC-AGI-1 | 400 | bbox | Bounding-box actions for structured edits |
28+
| `jaxarc/concept` | ConceptARC | ~40 | point | Tasks grouped by reasoning concept |
29+
30+
## Customising Behaviour
31+
32+
### Datasets
33+
34+
JaxARC supports four ARC datasets. Set the dataset via the `env.scenario.name` config:
35+
36+
- **Mini** (`env.scenario.name=Mini`): 70 simplified tasks from MiniARC. Good for debugging and prototyping.
37+
- **AGI1** (`env.scenario.name=AGI1-train`): 400 official ARC-AGI-1 training tasks. The standard RL benchmark. Use `AGI1-eval` for the evaluation split.
38+
- **AGI2** (`env.scenario.name=AGI2-train`): ARC-AGI-2 competition tasks. Use `AGI2-eval` for the evaluation split.
39+
- **ConceptARC** (`env.scenario.name=Concept-SameDifferent`): Tasks grouped by abstract reasoning concepts. Replace `SameDifferent` with any concept name.
40+
41+
Available ConceptARC concepts: `AboveBelow`, `Center`, `CleanUp`, `CompleteShape`, `Copy`, `Count`, `ExtendToBoundary`, `ExtractObjects`, `FilledNotFilled`, `HorizontalVertical`, `InsideOutside`, `MoveToBoundary`, `Order`, `SameDifferent`, `TopBottom2D`, `TopBottom3D`.
42+
43+
### Action Modes
44+
45+
JaxARC offers three action modes. Override via `env.action.mode`:
46+
47+
```bash
48+
# Point actions (default) — select individual cells
49+
python stoix/systems/ppo/anakin/ff_ppo.py env=jaxarc/default env.action.mode=point
50+
51+
# Bounding-box actions — select rectangular regions
52+
python stoix/systems/ppo/anakin/ff_ppo.py env=jaxarc/default env.action.mode=bbox
53+
```
54+
55+
- **point**: Agent selects one cell at a time (row, col, color). Simple but large action space.
56+
- **bbox**: Agent selects rectangular regions (top-left, bottom-right, color). Enables structured edits.
57+
- **mask**: Full grid mask specification. Most expressive but largest action space.
58+
59+
### Observation Wrappers
60+
61+
Three observation components can be toggled independently:
62+
63+
```yaml
64+
observation_wrappers:
65+
answer_grid: true # Include the current answer grid state
66+
input_grid: true # Include the input grid (task specification)
67+
contextual: true # Include task context (episode step, etc.)
68+
```
69+
70+
## Key Metrics
71+
72+
JaxARC provides domain-specific metrics alongside the standard Stoix `episode_return` and `episode_length`:
73+
74+
| Metric | Description |
75+
|--------|-------------|
76+
| `best_similarity` | Peak grid similarity achieved during the episode (0–1) |
77+
| `solved` | Whether the agent produced a perfect solution |
78+
| `steps_to_solve` | Number of steps taken to first solve (if solved) |
79+
| `final_similarity` | Grid similarity at episode termination (0–1) |
80+
| `was_truncated` | Whether the episode hit the step limit without solving |
81+
82+
These are emitted via JaxARC's `ExtendedMetrics` wrapper and appear in `timestep.extras["episode_metrics"]`.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ dependencies = [
141141
"gymnasium>=1.1.1",
142142
"huggingface-hub>=0.30.1",
143143
"hydra-core>=1.3.2",
144+
"jaxarc>=1.0.3",
144145
"jax>=0.4.25,<0.6.0",
145146
"jaxlib>=0.5.3",
146147
"jumanji>=1.0.0",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ARC-AGI-1 with bounding-box actions — demonstrates bbox action mode.
2+
# Bbox actions let the agent select rectangular regions instead of individual cells,
3+
# reducing the action space as compared to mask selection and enabling more structured edits.
4+
env_name: jaxarc
5+
6+
scenario:
7+
name: AGI1-train
8+
9+
action:
10+
mode: bbox # point | bbox | mask
11+
12+
observation_wrappers:
13+
answer_grid: true
14+
input_grid: true
15+
contextual: true
16+
17+
eval_metric: episode_return
18+
19+
wrapper:
20+
_target_: stoa.FlattenObservationWrapper
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# ARC-AGI-1 Training Set — Standard ARC benchmark for RL research.
2+
# Uses the official training split (400 tasks) with point-based actions.
3+
env_name: jaxarc
4+
5+
scenario:
6+
name: AGI1-train
7+
8+
action:
9+
mode: point # point | bbox | mask
10+
11+
observation_wrappers:
12+
answer_grid: true
13+
input_grid: true
14+
contextual: true
15+
16+
eval_metric: episode_return
17+
18+
wrapper:
19+
_target_: stoa.FlattenObservationWrapper
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ConceptARC — SameDifferent concept group.
2+
# ConceptARC organises tasks by abstract reasoning concepts.
3+
# Use "Concept-{ConceptName}" as the scenario to focus on a single concept:
4+
# AboveBelow, Center, CleanUp, CompleteShape, Copy, Count,
5+
# ExtendToBoundary, ExtractObjects, FilledNotFilled, HorizontalVertical,
6+
# InsideOutside, MoveToBoundary, Order, SameDifferent, TopBottom2D, TopBottom3D
7+
env_name: jaxarc
8+
9+
scenario:
10+
name: Concept-SameDifferent
11+
12+
action:
13+
mode: point # point | bbox | mask
14+
15+
observation_wrappers:
16+
answer_grid: true
17+
input_grid: true
18+
contextual: true
19+
20+
eval_metric: episode_return
21+
22+
wrapper:
23+
_target_: stoa.FlattenObservationWrapper
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ---Environment Configs---
2+
env_name: jaxarc
3+
4+
scenario:
5+
name: "Mini-Colony_Expansion_2_l6d2q1yx5npw0qdrnzn"
6+
task_name: mini
7+
8+
action:
9+
mode: point # point | bbox | mask
10+
11+
observation_wrappers:
12+
answer_grid: true
13+
input_grid: true
14+
contextual: true
15+
16+
# Defines the metric that will be used to evaluate the performance of the agent.
17+
# This metric is returned at the end of an experiment and can be used for hyperparameter tuning.
18+
eval_metric: episode_return
19+
20+
# Flatten multi-dimensional observation (4, 5, 5, 13) -> (1300,) for MLP networks.
21+
# Remove this wrapper when using CNN networks (e.g., network=jaxarc/arc_shallow_cnn).
22+
wrapper:
23+
_target_: stoa.FlattenObservationWrapper

stoix/utils/make_env.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,50 @@ def make_debug_env(scenario_name: str, config: DictConfig) -> Tuple[Environment,
304304
return env, eval_env
305305

306306

307+
def make_jaxarc_env(scenario_name: str, config: DictConfig) -> Tuple[Environment, Environment]:
308+
"""Creates and wraps a JaxARC environment for ARC puzzle tasks.
309+
310+
JaxARC environments are natively Stoa-compatible, so no adapter is needed.
311+
Domain-specific wrapper application (action, observation) is delegated to
312+
JaxARC's factory function. ExtendedMetrics is applied after RecordEpisodeMetrics
313+
so that domain-specific metrics merge correctly with episode metrics.
314+
"""
315+
try:
316+
from jaxarc.stoix_adapter import make_jaxarc_env as _make_jaxarc
317+
from jaxarc.wrappers import ExtendedMetrics
318+
except ImportError as e:
319+
raise ImportError(
320+
"JaxARC is required for 'jaxarc' environments. Install it with: pip install jaxarc"
321+
) from e
322+
323+
env, eval_env = _make_jaxarc(config)
324+
env, eval_env = apply_optional_wrappers((env, eval_env), config)
325+
326+
# Apply core wrappers with ExtendedMetrics injected after RecordEpisodeMetrics.
327+
# ExtendedMetrics must come after REM so it can merge its fields into the
328+
# episode_metrics dict that REM creates, rather than being overwritten by it.
329+
# Note: only train_env gets core wrappers (standard Stoix pattern).
330+
env = AddRNGKey(env)
331+
env = RecordEpisodeMetrics(env)
332+
env = ExtendedMetrics(env)
333+
334+
if config.env.get("use_optimistic_reset", False):
335+
env = OptimisticResetVmapWrapper(
336+
env,
337+
config.arch.num_envs,
338+
min(config.env.get("reset_ratio", 16), config.arch.num_envs),
339+
next_obs_in_extras=True,
340+
)
341+
else:
342+
if config.env.get("use_cached_auto_reset", False):
343+
env = CachedAutoResetWrapper(env, next_obs_in_extras=True)
344+
else:
345+
env = AutoResetWrapper(env, next_obs_in_extras=True)
346+
env = VmapWrapper(env)
347+
348+
return env, eval_env
349+
350+
307351
def make_popjym_env(scenario_name: str, config: DictConfig) -> Tuple[Environment, Environment]:
308352
"""Creates and wraps a POPJym environment."""
309353
import popjym
@@ -378,6 +422,7 @@ def make_playground_env(scenario_name: str, config: DictConfig) -> Tuple[Environ
378422
"gymnax": make_gymnax_env,
379423
"brax": make_brax_env,
380424
"craftax": make_craftax_env,
425+
"jaxarc": make_jaxarc_env,
381426
"popgym_arcade": make_popgym_arcade_env,
382427
"xland_minigrid": make_xland_minigrid_env,
383428
"popjym": make_popjym_env,

0 commit comments

Comments
 (0)