Update README with full instructions
Browse files
README.md
CHANGED
|
@@ -1,80 +1,94 @@
|
|
| 1 |
# NeuroGolf Solver
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
##
|
| 6 |
-
|
| 7 |
-
- Expected **~140+** with 30s budget on faster hardware
|
| 8 |
|
| 9 |
-
##
|
| 10 |
|
| 11 |
-
### 1. Clone & setup
|
| 12 |
```bash
|
|
|
|
| 13 |
git clone https://huggingface.co/rogermt/neurogolf-solver
|
| 14 |
cd neurogolf-solver
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
git clone --depth 1 https://github.com/fchollet/ARC-AGI.git
|
| 17 |
-
```
|
| 18 |
|
| 19 |
-
#
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
python neurogolf_solver.py --data_dir ARC-AGI/data/training/ --output_dir submission --conv_budget 30
|
| 23 |
|
| 24 |
-
#
|
| 25 |
-
python neurogolf_solver.py --
|
| 26 |
|
| 27 |
-
#
|
| 28 |
-
python neurogolf_solver.py --
|
| 29 |
-
```
|
| 30 |
|
| 31 |
-
#
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
| 34 |
```
|
| 35 |
|
| 36 |
-
##
|
| 37 |
```python
|
| 38 |
import zipfile, os
|
| 39 |
with zipfile.ZipFile('submission.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
|
| 40 |
for f in sorted(os.listdir('submission')):
|
| 41 |
if f.endswith('.onnx'):
|
| 42 |
zf.write(os.path.join('submission', f), f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
1. **Conv solver** (most tasks): `Slice[1,10,H,W] -> Conv2d -> ArgMax -> OneHot -> Pad[1,10,30,30]`
|
| 50 |
-
- Learns optimal conv weights via least-squares on one-hot encoded patches
|
| 51 |
-
- Tries kernel sizes 1,3,5,...,29 and picks smallest that fits perfectly
|
| 52 |
-
- Also tries with bias term for better boundary handling
|
| 53 |
-
|
| 54 |
-
2. **Analytical solvers** (fast, tiny models):
|
| 55 |
-
- `identity`: Identity op
|
| 56 |
-
- `color_map`: 1x1 conv (channel permutation)
|
| 57 |
-
- `transpose`: Transpose dims 2,3
|
| 58 |
-
- `flip`: GatherElements with reversed indices
|
| 59 |
-
- `rotate`: GatherElements with rotated indices
|
| 60 |
-
- `tile`: Slice -> Tile -> Pad
|
| 61 |
-
- `upscale`: GatherElements with repeated indices
|
| 62 |
-
- `concat`: GatherElements with block-transformed indices
|
| 63 |
-
- `spatial_gather`: GatherElements with per-pixel source mapping
|
| 64 |
-
- `constant`: Multiply by 0, add constant
|
| 65 |
-
|
| 66 |
-
## Format
|
| 67 |
-
- Input: `[1, 10, 30, 30]` float32 (one-hot encoded grid, padded to 30x30)
|
| 68 |
-
- Output: `[1, 10, 30, 30]` float32 (one-hot encoded grid)
|
| 69 |
-
- Scoring: `(output > 0.0).astype(float)` must match expected one-hot
|
| 70 |
-
- ONNX opset 10, IR version 10
|
| 71 |
-
|
| 72 |
-
## Key Insight
|
| 73 |
-
The critical trick is **Slice -> Conv -> ArgMax -> OneHot -> Pad**:
|
| 74 |
-
- Slice extracts the actual grid from the 30x30 padded input (avoiding color-0 boundary issues)
|
| 75 |
-
- Conv applies the learned transformation with zero-padding
|
| 76 |
-
- ArgMax finds the winning color channel
|
| 77 |
-
- OneHot converts back to clean one-hot (eliminates numerical precision issues)
|
| 78 |
-
- Pad restores to 30x30
|
| 79 |
-
|
| 80 |
-
Without ArgMax+OneHot, slight numerical noise from the conv causes validation failures.
|
|
|
|
| 1 |
# NeuroGolf Solver
|
| 2 |
|
| 3 |
+
Builds minimal ONNX networks for ARC-AGI tasks. Currently solves **127/400** on CPU (15s budget). With more time budget on faster hardware, expected **~140+**.
|
| 4 |
|
| 5 |
+
## Repo
|
| 6 |
+
https://huggingface.co/rogermt/neurogolf-solver
|
|
|
|
| 7 |
|
| 8 |
+
## Quick Start
|
| 9 |
|
|
|
|
| 10 |
```bash
|
| 11 |
+
# 1. Clone
|
| 12 |
git clone https://huggingface.co/rogermt/neurogolf-solver
|
| 13 |
cd neurogolf-solver
|
| 14 |
+
|
| 15 |
+
# 2. Install deps
|
| 16 |
+
pip install numpy onnx onnxruntime # or onnxruntime-gpu for CUDA
|
| 17 |
+
|
| 18 |
+
# 3. Get ARC data
|
| 19 |
git clone --depth 1 https://github.com/fchollet/ARC-AGI.git
|
|
|
|
| 20 |
|
| 21 |
+
# 4. Run (pick your config)
|
| 22 |
+
# CPU, 30s per task (~5 min total):
|
| 23 |
+
python neurogolf_solver.py --device cpu --conv_budget 30
|
|
|
|
| 24 |
|
| 25 |
+
# CPU, 60s per task (~10 min, more tasks solved):
|
| 26 |
+
python neurogolf_solver.py --device cpu --conv_budget 60
|
| 27 |
|
| 28 |
+
# CUDA (if onnxruntime-gpu installed):
|
| 29 |
+
python neurogolf_solver.py --device cuda --conv_budget 60
|
|
|
|
| 30 |
|
| 31 |
+
# Auto-detect device:
|
| 32 |
+
python neurogolf_solver.py --conv_budget 60
|
| 33 |
+
|
| 34 |
+
# 5. Results in submission/ directory
|
| 35 |
+
ls submission/*.onnx | wc -l
|
| 36 |
```
|
| 37 |
|
| 38 |
+
## Create submission.zip for Kaggle
|
| 39 |
```python
|
| 40 |
import zipfile, os
|
| 41 |
with zipfile.ZipFile('submission.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
|
| 42 |
for f in sorted(os.listdir('submission')):
|
| 43 |
if f.endswith('.onnx'):
|
| 44 |
zf.write(os.path.join('submission', f), f)
|
| 45 |
+
print(f"Created submission.zip: {os.path.getsize('submission.zip')/1024:.0f} KB")
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
## How It Works
|
| 49 |
+
|
| 50 |
+
**Format:** Input/output = `[1, 10, 30, 30]` one-hot float32. ONNX opset 10, IR version 10.
|
| 51 |
+
|
| 52 |
+
**Main pipeline (conv solver):**
|
| 53 |
```
|
| 54 |
+
Input [1,10,30,30] -> Slice [1,10,H,W] -> Conv2d -> ArgMax -> OneHot -> Pad [1,10,30,30]
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
- Learns optimal conv weights via **least-squares** on one-hot patches
|
| 58 |
+
- Tries kernel sizes 1, 3, 5, ..., 29 (smallest first)
|
| 59 |
+
- Also tries with bias for better boundary handling
|
| 60 |
+
- ArgMax + OneHot eliminates numerical precision issues
|
| 61 |
+
|
| 62 |
+
**Analytical solvers** (instant, tiny models): identity, color_map (1x1 conv), transpose, flip, rotate, tile, upscale, concat, spatial_gather, constant.
|
| 63 |
+
|
| 64 |
+
## Key Parameters
|
| 65 |
+
|
| 66 |
+
| Flag | Default | Description |
|
| 67 |
+
|------|---------|-------------|
|
| 68 |
+
| `--device` | `auto` | `cpu`, `cuda`, or `auto` |
|
| 69 |
+
| `--conv_budget` | `30` | Seconds per task for conv solver. More = more tasks solved |
|
| 70 |
+
| `--data_dir` | `ARC-AGI/data/training/` | Path to task JSONs |
|
| 71 |
+
| `--output_dir` | `submission` | Where to save .onnx files |
|
| 72 |
+
| `--kaggle` | off | Use Kaggle task format (task001.json) |
|
| 73 |
+
| `--tasks` | all | Comma-separated task numbers (e.g., `1,2,3`) |
|
| 74 |
+
|
| 75 |
+
## Architecture of generated ONNX models
|
| 76 |
+
|
| 77 |
+
Each .onnx file is a tiny network, typically:
|
| 78 |
+
- **Same-shape tasks**: Single Conv2d layer (10→10 channels, kernel 1-29)
|
| 79 |
+
- **Different-shape tasks**: GatherElements-based pixel remapping
|
| 80 |
+
- **Cost** = MACs + memory_bytes + params → **Score** = max(1, 25 - ln(cost))
|
| 81 |
+
|
| 82 |
+
## What's NOT solved yet (273 tasks)
|
| 83 |
+
|
| 84 |
+
- Variable-shape tasks (input size differs across examples) — need dynamic ONNX
|
| 85 |
+
- Tasks requiring multi-step reasoning (flood fill, gravity, object detection)
|
| 86 |
+
- Tasks where the transformation depends on counting/global properties
|
| 87 |
+
- Large grids where conv kernel > 29 is needed
|
| 88 |
+
|
| 89 |
+
## Feedback logs
|
| 90 |
|
| 91 |
+
After running, please share the full terminal output — especially:
|
| 92 |
+
1. The "Solved: X/400" line
|
| 93 |
+
2. Any errors
|
| 94 |
+
3. Total time taken
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|