File size: 5,066 Bytes
b8deeea
872fabe
dc5a945
872fabe
281319b
872fabe
2d6fea2
872fabe
b8deeea
 
 
29fae7c
281319b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b8deeea
872fabe
5d81668
 
 
b8deeea
 
 
 
5d81668
b8deeea
fff44ad
b8deeea
 
 
 
281319b
 
 
dc5a945
281319b
05d80c8
281319b
2d6fea2
281319b
 
 
b8deeea
281319b
 
 
 
b8deeea
281319b
 
 
 
 
 
b8deeea
281319b
05d80c8
872fabe
281319b
b8deeea
281319b
 
 
 
 
 
 
 
 
b8deeea
872fabe
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# NeuroGolf Solver

Builds minimal ONNX networks for ARC-AGI tasks. Modular Python package with opset 10-17, zero-cost Slice-based transforms + embedded trained weights.

**Public LB: 5331** (V97, 386/400 tasks solved by our solver)

## Target: LB > 6043

submission-6043.zip already scored 6043 on Kaggle. It's in this repo.
The models inside it are NOT generated by our solver — they come from an external source.
To beat 6043 with OUR solver, we need to reverse-engineer those models into DSL solver code.

---

## ⚠️ MANDATORY: Use neurogolf_utils.py for ALL validation and scoring

**`own-solver/neurogolf_utils.py` is the official Kaggle scoring kernel. It is the ONLY source of truth.**

Any script that validates models or measures cost MUST use it. Do NOT write your own validator. Do NOT write your own cost estimator. Do NOT silently remove it when it crashes — debug it and fix the calling code instead.

### What it provides:
- `sanitize_model(model)` — rename tensors to safe names (Kaggle does this before scoring)
- `score_network(sanitized, trace_path)` — returns `(memory, params)` using ORT Profiler
- `verify_network(network, task_num, examples)` — full validation + scoring
- `convert_to_numpy(example)` — encode grid to one-hot tensor
- `run_network(session, input)` — run inference with `> 0.0` thresholding
- `calculate_memory(model, trace_path)` — ORT Profiler memory measurement
- `calculate_params(model)` — official param counting

### How to use it for validation:
```python
from neurogolf_utils import sanitize_model, score_network, convert_to_numpy, run_network
import onnxruntime

# 1. Load and sanitize
model = onnx.load(path)
sanitized = sanitize_model(model)

# 2. Create session with profiling
options = onnxruntime.SessionOptions()
options.enable_profiling = True
options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_DISABLE_ALL
session = onnxruntime.InferenceSession(sanitized.SerializeToString(), options)

# 3. Validate against examples
for example in all_examples:
    benchmark = convert_to_numpy(example)
    if benchmark is None: continue
    output = run_network(session, benchmark["input"])
    if not np.array_equal(output, benchmark["output"]):
        # FAILED

# 4. Get score
trace_path = session.end_profiling()
memory, params = score_network(sanitized, trace_path)
cost = memory + params
score = max(1.0, 25.0 - math.log(max(1.0, cost)))
```

### Rules for agents:
1. **NEVER** write your own `validate_model()` function — use `neurogolf_utils.py`
2. **NEVER** write your own `measure_cost()` function — use `score_network()`
3. **NEVER** silently catch errors from `neurogolf_utils.py` — log them with full traceback
4. **NEVER** remove ORT profiler and replace with "static estimation" — static estimation is WRONG (proven: gives 5879 when Kaggle gives 5322)
5. If `neurogolf_utils.py` crashes, the bug is in YOUR calling code, not in the utils

---

## Scoring Formula (neurogolf_utils.py, May 14)

```python
score = max(1.0, 25.0 - math.log(max(1.0, memory + params)))
```
- memory = ORT Profiler intermediate tensor bytes (excludes input/output)
- params = initializer element count + Constant element count
- Initializer BYTES are NOT in memory — only element counts go to params
- NO MACs (removed May 4)

## What We Have

| Source | LB Score | Origin |
|--------|----------|--------|
| submission-6043.zip | 6043 | External. Not from our solver. Needs reverse-engineering. |
| submission-5743.zip | 5743 | External. Partially reverse-engineered into wave22. |
| submission-v90.zip | 5322 | Our solver output (V90). |
| V97 (solver only) | 5331 | Our solver with wave23. |
| V5 (merged) | 5748 | 6043 base + 5743 overrides (partial validation). |

## Pipeline

### Solver only (generates models from scratch):
```bash
cd own-solver
python -m neurogolf_solver.main \
  --kaggle \
  --data_dir /kaggle/input/competitions/neurogolf-2026 \
  --output_dir /kaggle/working/submission \
  --fallback_zip fallback_unsolved.zip \
  --conv_budget 5.0
```

### Merge (use 6043 as base, override with validated cheaper models):
```bash
cd own-solver
python merge_safe.py \
  --sub_6043 ../submission-6043.zip \
  --sub_5743 ../submission-5743.zip \
  --data_dir /kaggle/input/competitions/neurogolf-2026 \
  --output_zip /kaggle/working/merged.zip
```

## Key Files

| File | Purpose |
|------|---------|
| `neurogolf_utils.py` | **OFFICIAL Kaggle scoring kernel. USE THIS FOR ALL VALIDATION AND SCORING.** |
| `neurogolf_solver/` | Our solver package (generates ONNX models from task data) |
| `merge_safe.py` | Safe merger using neurogolf_utils.py for validation + scoring |
| `merge_best_of_both.py` | Old merger (DO NOT USE — uses broken static cost estimation) |
| `stage1_trivial_optimizer.py` | Rebuilds trivial tasks with cheaper architecture |
| `sign_corrected_conv.py` | Fits direct Conv→output weights (3/18 working) |
| `V90_IMPROVEMENT_PLAN.md` | Documented analysis of improvement paths |

## Repo

https://huggingface.co/rogermt/neurogolf-solver