Spaces:
Running
Running
Update logbook: Repro - NonZero: Interaction-Guided Exploration for Multi-Agent Monte Carlo Tree Search
Browse files- logbook.json +3 -3
- pages/claim-1-low-dimensional-nonlinear-surrogate/page.md +1 -295
- pages/claim-2-regret-bound-theorem-3-5/page.md +8 -2
- pages/claim-3-efficiency-separation-theorem-3-7/page.md +1 -8
- pages/claim-4-matgame-8-agent-10-action-nonlinear/page.md +1 -322
- pages/claim-5-smac-win-rate/page.md +1 -1
- pages/claim-6-smacv2-win-rate-ablations/page.md +1 -1
- pages/conclusion/page.md +1 -36
- pages/executive-summary/page.md +1 -1
- workspace.json +1 -17
logbook.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
| 10 |
"icml2026-repro",
|
| 11 |
"paper-Jh6gq9QsFa"
|
| 12 |
],
|
| 13 |
-
"updated_at": "2026-08-
|
| 14 |
"root": {
|
| 15 |
"slug": "index",
|
| 16 |
"title": "Repro - NonZero: Interaction-Guided Exploration for Multi-Agent Monte Carlo Tree Search",
|
|
@@ -73,10 +73,10 @@
|
|
| 73 |
"total_size": 0,
|
| 74 |
"bucket_id": null
|
| 75 |
},
|
| 76 |
-
"agent_view_tokens":
|
| 77 |
"trace_view_tokens": 10,
|
| 78 |
"workspace_view_tokens": 8,
|
| 79 |
-
"revision": "
|
| 80 |
"workspace_ref": {
|
| 81 |
"repo_id": "byte-vortex/nonzero-repro-artifacts",
|
| 82 |
"repo_type": "bucket",
|
|
|
|
| 10 |
"icml2026-repro",
|
| 11 |
"paper-Jh6gq9QsFa"
|
| 12 |
],
|
| 13 |
+
"updated_at": "2026-08-03T02:24:37+00:00",
|
| 14 |
"root": {
|
| 15 |
"slug": "index",
|
| 16 |
"title": "Repro - NonZero: Interaction-Guided Exploration for Multi-Agent Monte Carlo Tree Search",
|
|
|
|
| 73 |
"total_size": 0,
|
| 74 |
"bucket_id": null
|
| 75 |
},
|
| 76 |
+
"agent_view_tokens": 2940,
|
| 77 |
"trace_view_tokens": 10,
|
| 78 |
"workspace_view_tokens": 8,
|
| 79 |
+
"revision": "ac503ddb0980b9cbf6c5",
|
| 80 |
"workspace_ref": {
|
| 81 |
"repo_id": "byte-vortex/nonzero-repro-artifacts",
|
| 82 |
"repo_type": "bucket",
|
pages/claim-1-low-dimensional-nonlinear-surrogate/page.md
CHANGED
|
@@ -3,300 +3,6 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
Implemented the asinh-GLM surrogate eta(theta,a) = c*asinh(alpha*<theta,a>) exactly per Section 3.1, Eq. 2, plus the first-order (Eq. 3) and mixed second-order (Eq. 4) finite-difference operators. **Verified the paper's stated identity exactly**: eta(a^(u,v)) - eta(a) = Delta_u eta(a) + Delta_v eta(a) + Delta^2_{u,v} eta(a), confirmed to floating-point precision (error ~1.19e-7) via unit test. **[toy]** Verified the surrogate can learn real reward structure: trained on the 8-agent/10-action nonlinear MatGame environment, converged to R2=0.900 on held-out data, matching the theoretical ceiling set by the environment's injected noise variance (Gaussian sigma^2=4 + Uniform(-3,3)) -- essentially recovering all learnable signal. This used a simplified single-global-theta setup rather than the full state-conditioned hypernetwork architecture, so it validates the model family's expressiveness rather than the complete Claim 4 pipeline.
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
---
|
| 12 |
-
<!-- trackio-cell
|
| 13 |
-
{"type": "code", "id": "cell_fd591b62e1cb", "created_at": "2026-08-03T01:56:58+00:00", "title": "Run: hf claim1_mechanism_test.py (exit 0)", "command": ["hf", "jobs", "uv", "run", "--flavor", "cpu-basic", "--secrets", "HF_TOKEN", "claim1_mechanism_test.py"], "exit_code": 0, "duration_s": 138.56}
|
| 14 |
-
-->
|
| 15 |
-
````bash
|
| 16 |
-
$ hf jobs uv run --flavor cpu-basic --secrets HF_TOKEN claim1_mechanism_test.py
|
| 17 |
-
````
|
| 18 |
-
|
| 19 |
-
exit 0 · 138.6s
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
````python title=claim1_mechanism_test.py
|
| 23 |
-
# /// script
|
| 24 |
-
# dependencies = ["torch", "numpy"]
|
| 25 |
-
# ///
|
| 26 |
-
"""
|
| 27 |
-
Claim 1 -- toy-scale test of NonZero's actual proposal mechanism.
|
| 28 |
-
|
| 29 |
-
The paper's real claim isn't just "the surrogate can fit rewards" -- it's
|
| 30 |
-
that using the surrogate's first-order (single-agent) and second-order
|
| 31 |
-
(two-agent) difference operators to PROPOSE candidate action changes finds
|
| 32 |
-
good joint actions more efficiently than enumerating/random-sampling the
|
| 33 |
-
full joint-action space (Section 3, Section 3.1).
|
| 34 |
-
|
| 35 |
-
This script tests that directly: under an EQUAL evaluation budget, does
|
| 36 |
-
NonUCT-style guided local search find better joint actions than random
|
| 37 |
-
sampling, on the 8-agent/10-action nonlinear MatGame environment?
|
| 38 |
-
"""
|
| 39 |
-
|
| 40 |
-
import torch
|
| 41 |
-
import torch.nn as nn
|
| 42 |
-
import numpy as np
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
class MatgameNonZeroEnv:
|
| 46 |
-
def __init__(self, n_agents=8, n_actions=10, reward_type="nonlinear",
|
| 47 |
-
noise_std=2.0, noise_uniform_range=3.0, seed=None):
|
| 48 |
-
self.n_agents = n_agents
|
| 49 |
-
self.n_actions = n_actions
|
| 50 |
-
self.reward_type = reward_type
|
| 51 |
-
self.noise_std = noise_std
|
| 52 |
-
self.noise_uniform_range = noise_uniform_range
|
| 53 |
-
self._rng = np.random.default_rng(seed)
|
| 54 |
-
|
| 55 |
-
def joint_reward(self, actions):
|
| 56 |
-
base = float(np.sum(actions))
|
| 57 |
-
if self.reward_type == "linear":
|
| 58 |
-
return base
|
| 59 |
-
u = self._rng.normal(0.0, self.noise_std)
|
| 60 |
-
v = self._rng.uniform(-self.noise_uniform_range, self.noise_uniform_range)
|
| 61 |
-
return base + u + v
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
class AsinhGLMSurrogate:
|
| 65 |
-
def __init__(self, n_agents, n_actions, c=1.0, alpha=1.0):
|
| 66 |
-
self.n_agents, self.n_actions = n_agents, n_actions
|
| 67 |
-
self.nd = n_agents * n_actions
|
| 68 |
-
self.c, self.alpha = c, alpha
|
| 69 |
-
|
| 70 |
-
def one_hot(self, agent_actions):
|
| 71 |
-
agent_actions = torch.as_tensor(agent_actions, dtype=torch.long)
|
| 72 |
-
oh = torch.nn.functional.one_hot(agent_actions, num_classes=self.n_actions)
|
| 73 |
-
return oh.reshape(*agent_actions.shape[:-1], self.nd).float()
|
| 74 |
-
|
| 75 |
-
def eta(self, theta, a):
|
| 76 |
-
return self.c * torch.asinh(self.alpha * (theta * a).sum(dim=-1))
|
| 77 |
-
|
| 78 |
-
def neighbor(self, a, agent_idx, new_action):
|
| 79 |
-
a = a.clone()
|
| 80 |
-
s = agent_idx * self.n_actions
|
| 81 |
-
a[..., s:s + self.n_actions] = 0.0
|
| 82 |
-
a[..., s + new_action] = 1.0
|
| 83 |
-
return a
|
| 84 |
-
|
| 85 |
-
def neighbor_pair(self, a, agent_i, action_i, agent_j, action_j):
|
| 86 |
-
a = self.neighbor(a, agent_i, action_i)
|
| 87 |
-
a = self.neighbor(a, agent_j, action_j)
|
| 88 |
-
return a
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
def fit_surrogate(env, surrogate, n_samples=4000, n_epochs=1500, rng=None):
|
| 92 |
-
actions = rng.integers(0, env.n_actions, size=(n_samples, env.n_agents))
|
| 93 |
-
rewards = torch.tensor([env.joint_reward(a) for a in actions], dtype=torch.float32)
|
| 94 |
-
a_enc = surrogate.one_hot(torch.tensor(actions, dtype=torch.long))
|
| 95 |
-
|
| 96 |
-
theta = nn.Parameter(torch.zeros(surrogate.nd))
|
| 97 |
-
log_c, log_alpha = nn.Parameter(torch.zeros(())), nn.Parameter(torch.zeros(()))
|
| 98 |
-
opt = torch.optim.Adam([theta, log_c, log_alpha], lr=0.05)
|
| 99 |
-
sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=n_epochs)
|
| 100 |
-
|
| 101 |
-
def predict(a_batch):
|
| 102 |
-
return torch.exp(log_c) * torch.asinh(torch.exp(log_alpha) * (theta * a_batch).sum(dim=-1))
|
| 103 |
-
|
| 104 |
-
for _ in range(n_epochs):
|
| 105 |
-
opt.zero_grad()
|
| 106 |
-
loss = ((predict(a_enc) - rewards) ** 2).mean()
|
| 107 |
-
loss.backward()
|
| 108 |
-
opt.step()
|
| 109 |
-
sched.step()
|
| 110 |
-
return theta.detach()
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
def nonuct_guided_search(env, surrogate, theta, eval_budget, rng):
|
| 114 |
-
n_agents, n_actions = env.n_agents, env.n_actions
|
| 115 |
-
current = rng.integers(0, n_actions, size=n_agents)
|
| 116 |
-
best_reward = env.joint_reward(current)
|
| 117 |
-
evals_used = 1
|
| 118 |
-
|
| 119 |
-
while evals_used < eval_budget:
|
| 120 |
-
cur_enc = surrogate.one_hot(torch.tensor(current, dtype=torch.long))
|
| 121 |
-
cur_eta = surrogate.eta(theta, cur_enc).item()
|
| 122 |
-
|
| 123 |
-
best_candidate, best_delta, best_kind = None, -float("inf"), None
|
| 124 |
-
for agent_idx in range(n_agents):
|
| 125 |
-
for new_action in range(n_actions):
|
| 126 |
-
if new_action == current[agent_idx]:
|
| 127 |
-
continue
|
| 128 |
-
cand_enc = surrogate.neighbor(cur_enc, agent_idx, new_action)
|
| 129 |
-
delta = (surrogate.eta(theta, cand_enc) - cur_eta).item()
|
| 130 |
-
if delta > best_delta:
|
| 131 |
-
best_delta, best_candidate, best_kind = delta, (agent_idx, new_action), "first"
|
| 132 |
-
|
| 133 |
-
for i in range(n_agents):
|
| 134 |
-
for j in range(i + 1, n_agents):
|
| 135 |
-
for ai in range(n_actions):
|
| 136 |
-
if ai == current[i]:
|
| 137 |
-
continue
|
| 138 |
-
for aj in range(n_actions):
|
| 139 |
-
if aj == current[j]:
|
| 140 |
-
continue
|
| 141 |
-
cand_enc = surrogate.neighbor_pair(cur_enc, i, ai, j, aj)
|
| 142 |
-
delta = (surrogate.eta(theta, cand_enc) - cur_eta).item()
|
| 143 |
-
if delta > best_delta:
|
| 144 |
-
best_delta, best_candidate, best_kind = delta, (i, ai, j, aj), "second"
|
| 145 |
-
|
| 146 |
-
if best_candidate is None or evals_used >= eval_budget:
|
| 147 |
-
break
|
| 148 |
-
|
| 149 |
-
candidate_actions = current.copy()
|
| 150 |
-
if best_kind == "first":
|
| 151 |
-
agent_idx, new_action = best_candidate
|
| 152 |
-
candidate_actions[agent_idx] = new_action
|
| 153 |
-
else:
|
| 154 |
-
i, ai, j, aj = best_candidate
|
| 155 |
-
candidate_actions[i] = ai
|
| 156 |
-
candidate_actions[j] = aj
|
| 157 |
-
|
| 158 |
-
real_reward = env.joint_reward(candidate_actions)
|
| 159 |
-
evals_used += 1
|
| 160 |
-
|
| 161 |
-
if real_reward > best_reward:
|
| 162 |
-
current = candidate_actions
|
| 163 |
-
best_reward = real_reward
|
| 164 |
-
else:
|
| 165 |
-
break
|
| 166 |
-
|
| 167 |
-
return best_reward, evals_used
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
def random_search(env, eval_budget, rng):
|
| 171 |
-
best_reward = -float("inf")
|
| 172 |
-
for _ in range(eval_budget):
|
| 173 |
-
actions = rng.integers(0, env.n_actions, size=env.n_agents)
|
| 174 |
-
r = env.joint_reward(actions)
|
| 175 |
-
if r > best_reward:
|
| 176 |
-
best_reward = r
|
| 177 |
-
return best_reward
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
def main():
|
| 181 |
-
print("=" * 70)
|
| 182 |
-
print("NonZero reproduction -- Claim 1 mechanism test (toy scale)")
|
| 183 |
-
print("Testing: does surrogate-guided proposal beat random search")
|
| 184 |
-
print("under an EQUAL real-environment evaluation budget?")
|
| 185 |
-
print("=" * 70)
|
| 186 |
-
|
| 187 |
-
n_trials = 200
|
| 188 |
-
eval_budget = 15
|
| 189 |
-
|
| 190 |
-
rng_fit = np.random.default_rng(0)
|
| 191 |
-
env_fit = MatgameNonZeroEnv(n_agents=8, n_actions=10, reward_type="nonlinear", seed=1)
|
| 192 |
-
surrogate = AsinhGLMSurrogate(8, 10)
|
| 193 |
-
theta = fit_surrogate(env_fit, surrogate, rng=rng_fit)
|
| 194 |
-
print(f"\nSurrogate fit complete (theta trained on 4000 samples).")
|
| 195 |
-
|
| 196 |
-
guided_rewards, random_rewards = [], []
|
| 197 |
-
for trial in range(n_trials):
|
| 198 |
-
rng = np.random.default_rng(1000 + trial)
|
| 199 |
-
env = MatgameNonZeroEnv(n_agents=8, n_actions=10, reward_type="nonlinear", seed=2000 + trial)
|
| 200 |
-
|
| 201 |
-
g_reward, g_evals = nonuct_guided_search(env, surrogate, theta, eval_budget, rng)
|
| 202 |
-
guided_rewards.append(g_reward)
|
| 203 |
-
|
| 204 |
-
env2 = MatgameNonZeroEnv(n_agents=8, n_actions=10, reward_type="nonlinear", seed=2000 + trial)
|
| 205 |
-
rng2 = np.random.default_rng(1000 + trial)
|
| 206 |
-
r_reward = random_search(env2, eval_budget, rng2)
|
| 207 |
-
random_rewards.append(r_reward)
|
| 208 |
-
|
| 209 |
-
guided_mean, guided_std = np.mean(guided_rewards), np.std(guided_rewards)
|
| 210 |
-
random_mean, random_std = np.mean(random_rewards), np.std(random_rewards)
|
| 211 |
-
improvement = (guided_mean - random_mean) / abs(random_mean) * 100
|
| 212 |
-
|
| 213 |
-
print(f"\n[Results over {n_trials} trials, eval_budget={eval_budget}]")
|
| 214 |
-
print(f" Surrogate-guided search: {guided_mean:.2f} +/- {guided_std:.2f}")
|
| 215 |
-
print(f" Random search (baseline): {random_mean:.2f} +/- {random_std:.2f}")
|
| 216 |
-
print(f" Improvement: {improvement:+.1f}%")
|
| 217 |
-
|
| 218 |
-
print("\n" + "=" * 70)
|
| 219 |
-
print("SUMMARY")
|
| 220 |
-
if guided_mean > random_mean:
|
| 221 |
-
print(f" PASS: surrogate-guided proposal outperforms random search")
|
| 222 |
-
print(f" by {improvement:.1f}% under equal evaluation budget.")
|
| 223 |
-
print(f" This supports Claim 1's core mechanism at toy scale.")
|
| 224 |
-
else:
|
| 225 |
-
print(f" FAIL: surrogate-guided proposal did NOT outperform random search")
|
| 226 |
-
print(f" in this toy setting.")
|
| 227 |
-
print("=" * 70)
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
if __name__ == "__main__":
|
| 231 |
-
main()
|
| 232 |
-
|
| 233 |
-
````
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
````output
|
| 237 |
-
/usr/local/lib/python3.12/dist-packages/huggingface_hub/utils/_experimental.py:59: UserWarning: 'HfApi.run_uv_job' is experimental and might be subject to breaking changes in the future without prior notice. You can disable this warning by setting `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1` as environment variable.
|
| 238 |
-
warnings.warn(
|
| 239 |
-
Job started with ID: 6a6ff4e06b79c09949c200e0
|
| 240 |
-
View at: https://huggingface.co/jobs/byte-vortex/6a6ff4e06b79c09949c200e0
|
| 241 |
-
Downloading numpy (15.9MiB)
|
| 242 |
-
Downloading cuda-bindings (6.3MiB)
|
| 243 |
-
Downloading torch (502.2MiB)
|
| 244 |
-
Downloading nvidia-cusolver (191.6MiB)
|
| 245 |
-
Downloading nvidia-nccl-cu13 (196.4MiB)
|
| 246 |
-
Downloading nvidia-cuda-nvrtc (86.0MiB)
|
| 247 |
-
Downloading networkx (2.0MiB)
|
| 248 |
-
Downloading nvidia-nvshmem-cu13 (57.6MiB)
|
| 249 |
-
Downloading nvidia-nvjitlink (38.9MiB)
|
| 250 |
-
Downloading nvidia-cublas (403.5MiB)
|
| 251 |
-
Downloading nvidia-cufft (204.2MiB)
|
| 252 |
-
Downloading nvidia-curand (56.8MiB)
|
| 253 |
-
Downloading triton (188.6MiB)
|
| 254 |
-
Downloading nvidia-cusparselt-cu13 (162.3MiB)
|
| 255 |
-
Downloading nvidia-cufile (1.2MiB)
|
| 256 |
-
Downloading nvidia-cusparse (139.2MiB)
|
| 257 |
-
Downloading nvidia-cuda-cupti (10.2MiB)
|
| 258 |
-
Downloading sympy (6.0MiB)
|
| 259 |
-
Downloading nvidia-cuda-runtime (2.1MiB)
|
| 260 |
-
Downloading nvidia-cudnn-cu13 (349.2MiB)
|
| 261 |
-
Downloaded nvidia-cufile
|
| 262 |
-
Downloaded nvidia-cuda-runtime
|
| 263 |
-
Downloaded networkx
|
| 264 |
-
Downloaded cuda-bindings
|
| 265 |
-
Downloaded nvidia-cuda-cupti
|
| 266 |
-
Downloaded numpy
|
| 267 |
-
Downloaded nvidia-nvjitlink
|
| 268 |
-
Downloaded sympy
|
| 269 |
-
Downloaded nvidia-curand
|
| 270 |
-
Downloaded nvidia-nvshmem-cu13
|
| 271 |
-
Downloaded nvidia-cuda-nvrtc
|
| 272 |
-
Downloaded nvidia-cusparse
|
| 273 |
-
Downloaded nvidia-cusparselt-cu13
|
| 274 |
-
Downloaded nvidia-cusolver
|
| 275 |
-
Downloaded nvidia-nccl-cu13
|
| 276 |
-
Downloaded nvidia-cufft
|
| 277 |
-
Downloaded triton
|
| 278 |
-
Downloaded nvidia-cudnn-cu13
|
| 279 |
-
Downloaded nvidia-cublas
|
| 280 |
-
Downloaded torch
|
| 281 |
-
Installed 30 packages in 228ms
|
| 282 |
-
======================================================================
|
| 283 |
-
NonZero reproduction -- Claim 1 mechanism test (toy scale)
|
| 284 |
-
Testing: does surrogate-guided proposal beat random search
|
| 285 |
-
under an EQUAL real-environment evaluation budget?
|
| 286 |
-
======================================================================
|
| 287 |
-
|
| 288 |
-
Surrogate fit complete (theta trained on 4000 samples).
|
| 289 |
-
|
| 290 |
-
[Results over 200 trials, eval_budget=15]
|
| 291 |
-
Surrogate-guided search: 73.19 +/- 2.59
|
| 292 |
-
Random search (baseline): 51.04 +/- 4.58
|
| 293 |
-
Improvement: +43.4%
|
| 294 |
-
|
| 295 |
-
======================================================================
|
| 296 |
-
SUMMARY
|
| 297 |
-
PASS: surrogate-guided proposal outperforms random search
|
| 298 |
-
by 43.4% under equal evaluation budget.
|
| 299 |
-
This supports Claim 1's core mechanism at toy scale.
|
| 300 |
-
======================================================================
|
| 301 |
-
|
| 302 |
-
````
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_a26eb969299b", "created_at": "2026-08-03T02:23:41+00:00", "title": "Implemented the asinh-GLM surrogate eta(theta,a) = casinh(alpha<theta,a) exactl…"}
|
| 7 |
-->
|
| 8 |
Implemented the asinh-GLM surrogate eta(theta,a) = c*asinh(alpha*<theta,a>) exactly per Section 3.1, Eq. 2, plus the first-order (Eq. 3) and mixed second-order (Eq. 4) finite-difference operators. **Verified the paper's stated identity exactly**: eta(a^(u,v)) - eta(a) = Delta_u eta(a) + Delta_v eta(a) + Delta^2_{u,v} eta(a), confirmed to floating-point precision (error ~1.19e-7) via unit test. **[toy]** Verified the surrogate can learn real reward structure: trained on the 8-agent/10-action nonlinear MatGame environment, converged to R2=0.900 on held-out data, matching the theoretical ceiling set by the environment's injected noise variance (Gaussian sigma^2=4 + Uniform(-3,3)) -- essentially recovering all learnable signal. This used a simplified single-global-theta setup rather than the full state-conditioned hypernetwork architecture, so it validates the model family's expressiveness rather than the complete Claim 4 pipeline.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/claim-2-regret-bound-theorem-3-5/page.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_34a0f8b8583d", "created_at": "2026-08-03T02:23:42+00:00", "title": "Proof review (not a numerical claim)"}
|
| 7 |
-->
|
| 8 |
+
Actually reviewed the proof this time (arXiv:2605.00751v1, Appendix A.2-A.5), rather than skipping it -- this claim needs no compute, just reading.
|
| 9 |
+
|
| 10 |
+
**What holds up:** the overall proof strategy is a standard and sound template: (1) Lemma 3.3 shows one-step ascent modulo estimation error via a descent-lemma argument (first-order case) plus cubic-regularization (second-order/negative-curvature case); the algebra checks out exactly -- e.g. the linear error term <g_t,e_t> cancels exactly at step size 1/zeta_h, which is correct arithmetic, not hand-waving. (2) Lemma 3.4 bounds cumulative estimation error via Azuma-Hoeffding + sequential Rademacher complexity + Talagrand's contraction, giving the O(T^{3/4}) rate; this is a fairly standard online-to-batch / fast-rate argument and the WX*sqrt(T) bound for a norm-bounded linear class is a textbook result. (3) Theorem 3.5's proof is a clean telescoping sum combining (1) and (2); the final algebra (dividing through by the improvement rate nu(epsilon) to get K(epsilon)) matches the stated bound exactly.
|
| 11 |
+
|
| 12 |
+
**Two real gaps, not just nitpicks:** (a) Lemma 3.3's proof analyzes an idealized *continuous* gradient/cubic-regularized update in a latent embedding space (via the phi(a) embedding introduced in Appendix A.1), not the actual discrete NonUCT candidate-proposal rule described in Section 3.1 and Algorithm 1 (finite differences + argmax over a fixed candidate set C(s)). The paper doesn't show these two update rules are equivalent or bound the gap between them -- it's a common style of idealized-proxy analysis in this literature, but it means the theorem is proven for a model of the algorithm, not verified against the literal pseudocode in Algorithm 1. (b) The smoothness constants (zeta_h, zeta_3rd) and the dimension-dependent complexity term WX ~ sqrt(nd) used in Theorem 3.7's derivation are introduced via a generic Lipschitz/embedding argument (Appendix A.1) rather than computed concretely for the paper's actual architecture, which includes a hypernetwork-initialized theta (Section 3.3) -- a much richer model than the fixed linear/asinh-GLM class the complexity bound in Lemma 3.4 is derived for.
|
| 13 |
+
|
| 14 |
+
**Verdict:** the proof is internally consistent and uses correct, recognizable techniques throughout -- no obvious algebraic errors were found in Lemmas 3.3-3.4 or Theorem 3.5's combination step. The main open question, not resolved in the paper, is whether the idealized continuous-update analysis and the generic complexity constants actually transfer to the discrete, hypernetwork-based NonUCT mechanism used in practice. This is a genuine review, not a from-scratch re-derivation or a formal proof checker; no numerical claim is made here.
|
pages/claim-3-efficiency-separation-theorem-3-7/page.md
CHANGED
|
@@ -3,13 +3,6 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
Not attempted. Same reasoning as Claim 2 -- theoretical claim (Appendix A.6), proof review deprioritized given time constraints.
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
---
|
| 12 |
-
<!-- trackio-cell
|
| 13 |
-
{"type": "markdown", "id": "cell_9c209de3baa5", "created_at": "2026-08-03T01:58:08+00:00", "title": "Toy numerical illustration"}
|
| 14 |
-
-->
|
| 15 |
-
[toy numerical illustration] Not a formal proof-check of Theorem 3.7's exact bound (that would require verifying the proof in Appendix A.6, not code). Instead, numerically measured the guided-search budget needed to reach a near-optimal joint action as the number of agents (n) grows from 3 to 6, and compared against the size of the full joint-action space (d^n) that a standard UCB-style method would need to enumerate for comparable coverage. The resulting separation ratio grew from ~160x to ~90,394x -- steep, monotonic growth consistent with the theorem's claimed exponential advantage in n, though this illustrates the qualitative trend rather than verifying the theorem's precise constants.
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_ecbe6283c15e", "created_at": "2026-08-03T02:23:43+00:00", "title": "Not attempted. Same reasoning as Claim 2 -- theoretical claim (Appendix A.6), p…"}
|
| 7 |
-->
|
| 8 |
Not attempted. Same reasoning as Claim 2 -- theoretical claim (Appendix A.6), proof review deprioritized given time constraints.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/claim-4-matgame-8-agent-10-action-nonlinear/page.md
CHANGED
|
@@ -3,327 +3,6 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
**[toy / partial]** Built a generalized N-agent MatGame environment implementing the exact reward rule from Appendix D (linear = sum of agent action indices; nonlinear = linear sum + Gaussian(0,2^2) + Uniform(-3,3) noise). Sanity-checked reward scale against Table 1: random-policy episodes on the 8x10 nonlinear config average ~370-380 out of a 720 max, consistent with the paper's trained-baseline range of 587-712 sitting well above random. Confirmed the underlying MAZero codebase (which NonZero extends, per the paper's own Appendix C) builds and trains successfully on a single Kaggle T4 GPU, converging to the optimal joint policy (test score 100.0 +/- 0.0) on the repo's built-in matgame3 config. Began implementing NonUCT's selection rule as a C++ patch to MAZero's MCTS node scoring (cnode.h/cnode.cpp): added hooks for a precomputed surrogate score, blended additively into the existing pUCT formula, gated by a weight defaulting to 0 so baseline behavior is unaffected unless explicitly enabled. This patch compiles successfully. **Not completed**: the Cython bindings (cytree.pyx) needed to call these new C++ hooks from Python were not implemented, so no NonZero-vs-MAZero training comparison was run, and Table 1's actual numbers (697.1 vs 672.3) were not reproduced or falsified.
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
---
|
| 12 |
-
<!-- trackio-cell
|
| 13 |
-
{"type": "code", "id": "cell_68c7c619d5ee", "created_at": "2026-08-03T01:58:01+00:00", "title": "Run: hf claim4_toy_comparison.py (exit 0)", "command": ["hf", "jobs", "uv", "run", "--flavor", "cpu-basic", "--secrets", "HF_TOKEN", "claim4_toy_comparison.py"], "exit_code": 0, "duration_s": 54.53}
|
| 14 |
-
-->
|
| 15 |
-
````bash
|
| 16 |
-
$ hf jobs uv run --flavor cpu-basic --secrets HF_TOKEN claim4_toy_comparison.py
|
| 17 |
-
````
|
| 18 |
-
|
| 19 |
-
exit 0 · 54.5s
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
````python title=claim4_toy_comparison.py
|
| 23 |
-
|
| 24 |
-
# /// script
|
| 25 |
-
# dependencies = ["torch", "numpy"]
|
| 26 |
-
# ///
|
| 27 |
-
"""
|
| 28 |
-
Claim 4 -- toy-scale head-to-head comparison on the paper's exact
|
| 29 |
-
8-agent, 10-action nonlinear MatGame setting (Table 1). Vectorized
|
| 30 |
-
version: candidate generation uses precomputed batched tensor masks
|
| 31 |
-
instead of per-candidate Python loops, since the naive version is too
|
| 32 |
-
slow for 2000 decisions.
|
| 33 |
-
"""
|
| 34 |
-
|
| 35 |
-
import torch
|
| 36 |
-
import torch.nn as nn
|
| 37 |
-
import numpy as np
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
class MatgameNonZeroEnv:
|
| 41 |
-
def __init__(self, n_agents=8, n_actions=10, reward_type="nonlinear",
|
| 42 |
-
noise_std=2.0, noise_uniform_range=3.0, seed=None):
|
| 43 |
-
self.n_agents = n_agents
|
| 44 |
-
self.n_actions = n_actions
|
| 45 |
-
self.reward_type = reward_type
|
| 46 |
-
self.noise_std = noise_std
|
| 47 |
-
self.noise_uniform_range = noise_uniform_range
|
| 48 |
-
self._rng = np.random.default_rng(seed)
|
| 49 |
-
|
| 50 |
-
def joint_reward(self, actions):
|
| 51 |
-
base = float(np.sum(actions))
|
| 52 |
-
if self.reward_type == "linear":
|
| 53 |
-
return base
|
| 54 |
-
u = self._rng.normal(0.0, self.noise_std)
|
| 55 |
-
v = self._rng.uniform(-self.noise_uniform_range, self.noise_uniform_range)
|
| 56 |
-
return base + u + v
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
class VectorizedProposer:
|
| 60 |
-
def __init__(self, n_agents, n_actions, c=1.0, alpha=1.0):
|
| 61 |
-
self.n_agents, self.n_actions = n_agents, n_actions
|
| 62 |
-
self.nd = n_agents * n_actions
|
| 63 |
-
self.c, self.alpha = c, alpha
|
| 64 |
-
|
| 65 |
-
rows1 = n_agents * n_actions
|
| 66 |
-
self.agent1 = torch.zeros(rows1, dtype=torch.long)
|
| 67 |
-
self.action1 = torch.zeros(rows1, dtype=torch.long)
|
| 68 |
-
self.block_mask1 = torch.zeros(rows1, self.nd)
|
| 69 |
-
self.target1 = torch.zeros(rows1, self.nd)
|
| 70 |
-
r = 0
|
| 71 |
-
for i in range(n_agents):
|
| 72 |
-
for j in range(n_actions):
|
| 73 |
-
self.agent1[r], self.action1[r] = i, j
|
| 74 |
-
self.block_mask1[r, i * n_actions:(i + 1) * n_actions] = 1.0
|
| 75 |
-
self.target1[r, i * n_actions + j] = 1.0
|
| 76 |
-
r += 1
|
| 77 |
-
|
| 78 |
-
pairs = [(i, j) for i in range(n_agents) for j in range(i + 1, n_agents)]
|
| 79 |
-
rows2 = len(pairs) * n_actions * n_actions
|
| 80 |
-
self.pair_i = torch.zeros(rows2, dtype=torch.long)
|
| 81 |
-
self.pair_j = torch.zeros(rows2, dtype=torch.long)
|
| 82 |
-
self.action_i = torch.zeros(rows2, dtype=torch.long)
|
| 83 |
-
self.action_j = torch.zeros(rows2, dtype=torch.long)
|
| 84 |
-
self.block_mask2 = torch.zeros(rows2, self.nd)
|
| 85 |
-
self.target2 = torch.zeros(rows2, self.nd)
|
| 86 |
-
r = 0
|
| 87 |
-
for (i, j) in pairs:
|
| 88 |
-
for ai in range(n_actions):
|
| 89 |
-
for aj in range(n_actions):
|
| 90 |
-
self.pair_i[r], self.pair_j[r] = i, j
|
| 91 |
-
self.action_i[r], self.action_j[r] = ai, aj
|
| 92 |
-
self.block_mask2[r, i * n_actions:(i + 1) * n_actions] = 1.0
|
| 93 |
-
self.block_mask2[r, j * n_actions:(j + 1) * n_actions] = 1.0
|
| 94 |
-
self.target2[r, i * n_actions + ai] = 1.0
|
| 95 |
-
self.target2[r, j * n_actions + aj] = 1.0
|
| 96 |
-
r += 1
|
| 97 |
-
|
| 98 |
-
def one_hot(self, agent_actions):
|
| 99 |
-
agent_actions = torch.as_tensor(agent_actions, dtype=torch.long)
|
| 100 |
-
oh = torch.nn.functional.one_hot(agent_actions, num_classes=self.n_actions)
|
| 101 |
-
return oh.reshape(-1).float()
|
| 102 |
-
|
| 103 |
-
def eta(self, theta, a_batch):
|
| 104 |
-
return self.c * torch.asinh(self.alpha * (theta.unsqueeze(0) * a_batch).sum(dim=-1))
|
| 105 |
-
|
| 106 |
-
def best_candidate(self, theta, cur_enc, current_actions):
|
| 107 |
-
cur_eta = self.eta(theta, cur_enc.unsqueeze(0)).item()
|
| 108 |
-
|
| 109 |
-
cand1 = cur_enc.unsqueeze(0) * (1 - self.block_mask1) + self.target1
|
| 110 |
-
eta1 = self.eta(theta, cand1)
|
| 111 |
-
current_action1 = torch.as_tensor(current_actions)[self.agent1]
|
| 112 |
-
self_mask1 = (self.action1 == current_action1)
|
| 113 |
-
eta1 = eta1.masked_fill(self_mask1, -float("inf"))
|
| 114 |
-
delta1 = eta1 - cur_eta
|
| 115 |
-
best1_val, best1_idx = delta1.max(dim=0)
|
| 116 |
-
|
| 117 |
-
cand2 = cur_enc.unsqueeze(0) * (1 - self.block_mask2) + self.target2
|
| 118 |
-
eta2 = self.eta(theta, cand2)
|
| 119 |
-
cur_ai = torch.as_tensor(current_actions)[self.pair_i]
|
| 120 |
-
cur_aj = torch.as_tensor(current_actions)[self.pair_j]
|
| 121 |
-
self_mask2 = (self.action_i == cur_ai) | (self.action_j == cur_aj)
|
| 122 |
-
eta2 = eta2.masked_fill(self_mask2, -float("inf"))
|
| 123 |
-
delta2 = eta2 - cur_eta
|
| 124 |
-
best2_val, best2_idx = delta2.max(dim=0)
|
| 125 |
-
|
| 126 |
-
if best1_val.item() >= best2_val.item():
|
| 127 |
-
agent_idx, new_action = self.agent1[best1_idx].item(), self.action1[best1_idx].item()
|
| 128 |
-
candidate_actions = current_actions.copy()
|
| 129 |
-
candidate_actions[agent_idx] = new_action
|
| 130 |
-
else:
|
| 131 |
-
i, j = self.pair_i[best2_idx].item(), self.pair_j[best2_idx].item()
|
| 132 |
-
ai, aj = self.action_i[best2_idx].item(), self.action_j[best2_idx].item()
|
| 133 |
-
candidate_actions = current_actions.copy()
|
| 134 |
-
candidate_actions[i], candidate_actions[j] = ai, aj
|
| 135 |
-
|
| 136 |
-
return candidate_actions
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
def fit_surrogate(env, n_agents, n_actions, n_samples=4000, n_epochs=1500, rng=None):
|
| 140 |
-
actions = rng.integers(0, n_actions, size=(n_samples, n_agents))
|
| 141 |
-
rewards = torch.tensor([env.joint_reward(a) for a in actions], dtype=torch.float32)
|
| 142 |
-
onehots = torch.nn.functional.one_hot(torch.tensor(actions, dtype=torch.long), num_classes=n_actions)
|
| 143 |
-
a_enc = onehots.reshape(n_samples, -1).float()
|
| 144 |
-
|
| 145 |
-
nd = n_agents * n_actions
|
| 146 |
-
theta = nn.Parameter(torch.zeros(nd))
|
| 147 |
-
log_c, log_alpha = nn.Parameter(torch.zeros(())), nn.Parameter(torch.zeros(()))
|
| 148 |
-
opt = torch.optim.Adam([theta, log_c, log_alpha], lr=0.05)
|
| 149 |
-
sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=n_epochs)
|
| 150 |
-
|
| 151 |
-
for _ in range(n_epochs):
|
| 152 |
-
opt.zero_grad()
|
| 153 |
-
pred = torch.exp(log_c) * torch.asinh(torch.exp(log_alpha) * (theta * a_enc).sum(dim=-1))
|
| 154 |
-
loss = ((pred - rewards) ** 2).mean()
|
| 155 |
-
loss.backward()
|
| 156 |
-
opt.step()
|
| 157 |
-
sched.step()
|
| 158 |
-
return theta.detach()
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
def nonzero_style_decision(env, proposer, theta, budget, rng):
|
| 162 |
-
n_agents, n_actions = env.n_agents, env.n_actions
|
| 163 |
-
current = rng.integers(0, n_actions, size=n_agents)
|
| 164 |
-
best_reward = env.joint_reward(current)
|
| 165 |
-
evals_used = 1
|
| 166 |
-
|
| 167 |
-
while evals_used < budget:
|
| 168 |
-
cur_enc = proposer.one_hot(current)
|
| 169 |
-
candidate_actions = proposer.best_candidate(theta, cur_enc, current)
|
| 170 |
-
real_reward = env.joint_reward(candidate_actions)
|
| 171 |
-
evals_used += 1
|
| 172 |
-
|
| 173 |
-
if real_reward > best_reward:
|
| 174 |
-
current = candidate_actions
|
| 175 |
-
best_reward = real_reward
|
| 176 |
-
else:
|
| 177 |
-
break
|
| 178 |
-
|
| 179 |
-
return best_reward
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
def mazero_style_decision(env, budget, rng):
|
| 183 |
-
best_reward = -float("inf")
|
| 184 |
-
for _ in range(budget):
|
| 185 |
-
actions = rng.integers(0, env.n_actions, size=env.n_agents)
|
| 186 |
-
r = env.joint_reward(actions)
|
| 187 |
-
if r > best_reward:
|
| 188 |
-
best_reward = r
|
| 189 |
-
return best_reward
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
def main():
|
| 193 |
-
print("=" * 70)
|
| 194 |
-
print("NonZero reproduction -- Claim 4 toy comparison (vectorized)")
|
| 195 |
-
print("Setting: 8 agents, 10 actions, nonlinear (Table 1's hardest config)")
|
| 196 |
-
print("2000 sequential decisions, equal real-eval budget per decision")
|
| 197 |
-
print("=" * 70)
|
| 198 |
-
|
| 199 |
-
n_agents, n_actions = 8, 10
|
| 200 |
-
n_steps = 2000
|
| 201 |
-
budget_per_step = 15
|
| 202 |
-
|
| 203 |
-
rng_fit = np.random.default_rng(0)
|
| 204 |
-
env_fit = MatgameNonZeroEnv(n_agents=n_agents, n_actions=n_actions,
|
| 205 |
-
reward_type="nonlinear", seed=1)
|
| 206 |
-
theta = fit_surrogate(env_fit, n_agents, n_actions, rng=rng_fit)
|
| 207 |
-
proposer = VectorizedProposer(n_agents, n_actions)
|
| 208 |
-
print(f"\nSurrogate fit complete. Candidate masks precomputed "
|
| 209 |
-
f"({proposer.block_mask1.shape[0]} first-order + "
|
| 210 |
-
f"{proposer.block_mask2.shape[0]} second-order candidates/decision).")
|
| 211 |
-
|
| 212 |
-
nonzero_rewards, mazero_rewards = [], []
|
| 213 |
-
for step in range(n_steps):
|
| 214 |
-
env_a = MatgameNonZeroEnv(n_agents=n_agents, n_actions=n_actions,
|
| 215 |
-
reward_type="nonlinear", seed=5000 + step)
|
| 216 |
-
rng_a = np.random.default_rng(3000 + step)
|
| 217 |
-
nonzero_rewards.append(nonzero_style_decision(env_a, proposer, theta, budget_per_step, rng_a))
|
| 218 |
-
|
| 219 |
-
env_b = MatgameNonZeroEnv(n_agents=n_agents, n_actions=n_actions,
|
| 220 |
-
reward_type="nonlinear", seed=5000 + step)
|
| 221 |
-
rng_b = np.random.default_rng(3000 + step)
|
| 222 |
-
mazero_rewards.append(mazero_style_decision(env_b, budget_per_step, rng_b))
|
| 223 |
-
|
| 224 |
-
if (step + 1) % 400 == 0:
|
| 225 |
-
print(f" ...{step + 1}/{n_steps} decisions completed")
|
| 226 |
-
|
| 227 |
-
nz_mean, nz_std = np.mean(nonzero_rewards), np.std(nonzero_rewards)
|
| 228 |
-
mz_mean, mz_std = np.mean(mazero_rewards), np.std(mazero_rewards)
|
| 229 |
-
improvement = (nz_mean - mz_mean) / abs(mz_mean) * 100
|
| 230 |
-
|
| 231 |
-
print(f"\n[Results over {n_steps} decisions, budget={budget_per_step}/decision]")
|
| 232 |
-
print(f" NonZero-style (guided proposal): {nz_mean:.2f} +/- {nz_std:.2f}")
|
| 233 |
-
print(f" MAZero-style (random sampled): {mz_mean:.2f} +/- {mz_std:.2f}")
|
| 234 |
-
print(f" Improvement: {improvement:+.1f}%")
|
| 235 |
-
|
| 236 |
-
print("\n" + "=" * 70)
|
| 237 |
-
print("SUMMARY")
|
| 238 |
-
if nz_mean > mz_mean:
|
| 239 |
-
print(f" PASS (toy scale): NonZero-style guided proposal outperforms")
|
| 240 |
-
print(f" MAZero-style random sampling by {improvement:.1f}% under equal budget.")
|
| 241 |
-
else:
|
| 242 |
-
print(f" FAIL: guided proposal did NOT outperform the baseline.")
|
| 243 |
-
print("=" * 70)
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
if __name__ == "__main__":
|
| 247 |
-
main()
|
| 248 |
-
|
| 249 |
-
````
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
````output
|
| 253 |
-
/usr/local/lib/python3.12/dist-packages/huggingface_hub/utils/_experimental.py:59: UserWarning: 'HfApi.run_uv_job' is experimental and might be subject to breaking changes in the future without prior notice. You can disable this warning by setting `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1` as environment variable.
|
| 254 |
-
warnings.warn(
|
| 255 |
-
Job started with ID: 6a6ff5736b79c09949c200e4
|
| 256 |
-
View at: https://huggingface.co/jobs/byte-vortex/6a6ff5736b79c09949c200e4
|
| 257 |
-
Downloading nvidia-nvshmem-cu13 (57.6MiB)
|
| 258 |
-
Downloading numpy (15.9MiB)
|
| 259 |
-
Downloading cuda-bindings (6.3MiB)
|
| 260 |
-
Downloading nvidia-cufile (1.2MiB)
|
| 261 |
-
Downloading sympy (6.0MiB)
|
| 262 |
-
Downloading nvidia-cuda-runtime (2.1MiB)
|
| 263 |
-
Downloading networkx (2.0MiB)
|
| 264 |
-
Downloading nvidia-cublas (403.5MiB)
|
| 265 |
-
Downloading triton (188.6MiB)
|
| 266 |
-
Downloading nvidia-cusparse (139.2MiB)
|
| 267 |
-
Downloading torch (502.2MiB)
|
| 268 |
-
Downloading nvidia-cusparselt-cu13 (162.3MiB)
|
| 269 |
-
Downloading nvidia-curand (56.8MiB)
|
| 270 |
-
Downloading nvidia-nvjitlink (38.9MiB)
|
| 271 |
-
Downloading nvidia-cufft (204.2MiB)
|
| 272 |
-
Downloading nvidia-cusolver (191.6MiB)
|
| 273 |
-
Downloading nvidia-nccl-cu13 (196.4MiB)
|
| 274 |
-
Downloading nvidia-cudnn-cu13 (349.2MiB)
|
| 275 |
-
Downloading nvidia-cuda-cupti (10.2MiB)
|
| 276 |
-
Downloading nvidia-cuda-nvrtc (86.0MiB)
|
| 277 |
-
Downloaded nvidia-cufile
|
| 278 |
-
Downloaded nvidia-cuda-runtime
|
| 279 |
-
Downloaded networkx
|
| 280 |
-
Downloaded cuda-bindings
|
| 281 |
-
Downloaded nvidia-cuda-cupti
|
| 282 |
-
Downloaded numpy
|
| 283 |
-
Downloaded sympy
|
| 284 |
-
Downloaded nvidia-nvjitlink
|
| 285 |
-
Downloaded nvidia-curand
|
| 286 |
-
Downloaded nvidia-nvshmem-cu13
|
| 287 |
-
Downloaded nvidia-cuda-nvrtc
|
| 288 |
-
Downloaded nvidia-cusparse
|
| 289 |
-
Downloaded nvidia-cusparselt-cu13
|
| 290 |
-
Downloaded nvidia-cusolver
|
| 291 |
-
Downloaded nvidia-nccl-cu13
|
| 292 |
-
Downloaded nvidia-cufft
|
| 293 |
-
Downloaded triton
|
| 294 |
-
Downloaded nvidia-cublas
|
| 295 |
-
Downloaded nvidia-cudnn-cu13
|
| 296 |
-
Downloaded torch
|
| 297 |
-
Installed 30 packages in 222ms
|
| 298 |
-
======================================================================
|
| 299 |
-
NonZero reproduction -- Claim 4 toy comparison (vectorized)
|
| 300 |
-
Setting: 8 agents, 10 actions, nonlinear (Table 1's hardest config)
|
| 301 |
-
2000 sequential decisions, equal real-eval budget per decision
|
| 302 |
-
======================================================================
|
| 303 |
-
|
| 304 |
-
Surrogate fit complete. Candidate masks precomputed (80 first-order + 2800 second-order candidates/decision).
|
| 305 |
-
...400/2000 decisions completed
|
| 306 |
-
...800/2000 decisions completed
|
| 307 |
-
...1200/2000 decisions completed
|
| 308 |
-
...1600/2000 decisions completed
|
| 309 |
-
...2000/2000 decisions completed
|
| 310 |
-
|
| 311 |
-
[Results over 2000 decisions, budget=15/decision]
|
| 312 |
-
NonZero-style (guided proposal): 72.97 +/- 2.59
|
| 313 |
-
MAZero-style (random sampled): 50.84 +/- 4.51
|
| 314 |
-
Improvement: +43.5%
|
| 315 |
-
|
| 316 |
-
======================================================================
|
| 317 |
-
SUMMARY
|
| 318 |
-
PASS (toy scale): NonZero-style guided proposal outperforms
|
| 319 |
-
MAZero-style random sampling by 43.5% under equal budget.
|
| 320 |
-
======================================================================
|
| 321 |
-
|
| 322 |
-
````
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
---
|
| 326 |
-
<!-- trackio-cell
|
| 327 |
-
{"type": "markdown", "id": "cell_c2c6c6a643bb", "created_at": "2026-08-03T01:58:04+00:00", "title": "NonUCT integration -- deeper findings (not completed)"}
|
| 328 |
-
-->
|
| 329 |
-
Deeper investigation into wiring NonUCT into the real MCTS search (beyond the toy comparison above): confirmed each C++ tree node stores its own joint action (`int *action`) that led to it, and that Python-to-C++ bindings for setting a NonUCT weight/scores were successfully built and tested (see the batch-bindings patch). However, full integration requires more than initially scoped: child actions are sampled and deduplicated internally in C++ (variable count per node, unknown to Python in advance), meaning real wiring needs additional getters to query actual sampled actions per node after each expansion, a trained state-conditioned theta-head network (a real architecture/training-loop change), and careful indexing into the node pool. This was assessed as a substantial additional engineering effort beyond what could be safely completed and verified without live debugging capability, and was not completed. Documenting this honestly rather than shipping unverified wiring.
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_4ad8e1fda18d", "created_at": "2026-08-03T02:23:44+00:00", "title": "[toy / partial] Built a generalized N-agent MatGame environment implementing th…"}
|
| 7 |
-->
|
| 8 |
**[toy / partial]** Built a generalized N-agent MatGame environment implementing the exact reward rule from Appendix D (linear = sum of agent action indices; nonlinear = linear sum + Gaussian(0,2^2) + Uniform(-3,3) noise). Sanity-checked reward scale against Table 1: random-policy episodes on the 8x10 nonlinear config average ~370-380 out of a 720 max, consistent with the paper's trained-baseline range of 587-712 sitting well above random. Confirmed the underlying MAZero codebase (which NonZero extends, per the paper's own Appendix C) builds and trains successfully on a single Kaggle T4 GPU, converging to the optimal joint policy (test score 100.0 +/- 0.0) on the repo's built-in matgame3 config. Began implementing NonUCT's selection rule as a C++ patch to MAZero's MCTS node scoring (cnode.h/cnode.cpp): added hooks for a precomputed surrogate score, blended additively into the existing pUCT formula, gated by a weight defaulting to 0 so baseline behavior is unaffected unless explicitly enabled. This patch compiles successfully. **Not completed**: the Cython bindings (cytree.pyx) needed to call these new C++ hooks from Python were not implemented, so no NonZero-vs-MAZero training comparison was run, and Table 1's actual numbers (697.1 vs 672.3) were not reproduced or falsified.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/claim-5-smac-win-rate/page.md
CHANGED
|
@@ -3,6 +3,6 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
Not attempted. The official MAZero training recipe (which NonZero extends) targets an NVIDIA A100 80GB per the repository documentation; free-tier compute available (Kaggle T4/P100, 16GB) is well below this, and SMAC training runs reported in the paper likely require many hours even for baseline methods. A heavily reduced/short-horizon smoke test was considered but would not produce numbers comparable to Figure 1's claims, so was not attempted rather than reporting a misleading partial result.
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_a6506bc1727b", "created_at": "2026-08-03T02:23:45+00:00", "title": "Not attempted. The official MAZero training recipe (which NonZero extends) targ…"}
|
| 7 |
-->
|
| 8 |
Not attempted. The official MAZero training recipe (which NonZero extends) targets an NVIDIA A100 80GB per the repository documentation; free-tier compute available (Kaggle T4/P100, 16GB) is well below this, and SMAC training runs reported in the paper likely require many hours even for baseline methods. A heavily reduced/short-horizon smoke test was considered but would not produce numbers comparable to Figure 1's claims, so was not attempted rather than reporting a misleading partial result.
|
pages/claim-6-smacv2-win-rate-ablations/page.md
CHANGED
|
@@ -3,6 +3,6 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
Not attempted. Same reasoning as Claim 5 -- SMACv2 has the same compute requirements as SMAC, out of reach on available free-tier GPU.
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_4f4bc8f81ffd", "created_at": "2026-08-03T02:23:46+00:00", "title": "Not attempted. Same reasoning as Claim 5 -- SMACv2 has the same compute require…"}
|
| 7 |
-->
|
| 8 |
Not attempted. Same reasoning as Claim 5 -- SMACv2 has the same compute requirements as SMAC, out of reach on available free-tier GPU.
|
pages/conclusion/page.md
CHANGED
|
@@ -3,43 +3,8 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "artifact", "id": "
|
| 7 |
-->
|
| 8 |
**📦 Artifact** `nonzero-repro/repro-bundle:v1` · dataset
|
| 9 |
|
| 10 |
trackio-artifact://nonzero-repro/repro-bundle:v1
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
---
|
| 14 |
-
<!-- trackio-cell
|
| 15 |
-
{"type": "markdown", "id": "cell_41b739b9d8c4", "created_at": "2026-08-03T01:54:36+00:00", "title": "Acknowledgments"}
|
| 16 |
-
-->
|
| 17 |
-
This reproduction was completed with assistance from Claude (Anthropic), used as a coding/research agent throughout: reading and interpreting the paper, writing and debugging the environment/surrogate/C++ code, diagnosing build and Kaggle environment issues, and drafting this logbook. All claims of what was and wasn't verified reflect the actual code that was run and its outputs, checked at each step before being reported here.
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
---
|
| 21 |
-
<!-- trackio-cell
|
| 22 |
-
{"type": "markdown", "id": "cell_f763d79b3c3e", "created_at": "2026-08-03T01:57:03+00:00", "title": "Supporting code (corrected)"}
|
| 23 |
-
-->
|
| 24 |
-
All supporting code for this reproduction (the MatGame environment, asinh-GLM surrogate, validation script, and the NonUCT C++ patch) is available in this reproduction's Hugging Face Bucket:
|
| 25 |
-
|
| 26 |
-
hf://buckets/byte-vortex/nonzero-repro-artifacts
|
| 27 |
-
|
| 28 |
-
Browsable at: https://huggingface.co/buckets/byte-vortex/nonzero-repro-artifacts
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
---
|
| 32 |
-
<!-- trackio-cell
|
| 33 |
-
{"type": "markdown", "id": "cell_0f25ce87ab89", "created_at": "2026-08-03T01:58:04+00:00", "title": "Executive summary (updated)"}
|
| 34 |
-
-->
|
| 35 |
-
Partial reproduction of NonZero. Of the paper's 6 claims: Claim 1 was verified at toy scale with genuine evidence -- the finite-difference identity holds exactly, and a real Hugging Face Job run showed the paper's full proposal mechanism (first- and second-order difference operators) outperforming random search by 43.4% under equal evaluation budget. Claim 4 has a toy-scale empirical result (a real HF Job showing the same mechanism outperforming a MAZero-style random-sampling baseline by 43.5% on the paper's exact 8-agent/10-action/nonlinear configuration) plus validated supporting infrastructure (environment, baseline training pipeline, and a compiling C++ patch for NonUCT) -- but no full trained NonZero-vs-baseline comparison was completed, so Table 1's exact reported numbers (697.1 vs 672.3) were neither reproduced nor falsified. Claims 2-3 (theoretical proofs) and Claims 5-6 (SMAC/SMACv2) were not attempted: the former due to time constraints, the latter because the paper's own training recipe requires A100-class GPU hardware unavailable on free-tier compute.
|
| 36 |
-
|
| 37 |
-
## Scope & cost
|
| 38 |
-
|
| 39 |
-
| | This reproduction | Full replication |
|
| 40 |
-
|---|---|---|
|
| 41 |
-
| Scope | Claim 1 (verified, toy) + Claim 4 (toy empirical result + infrastructure) | All 6 claims incl. SMAC/SMACv2 |
|
| 42 |
-
| Hardware | Kaggle T4 (free tier) + Hugging Face Jobs (cpu-basic) | Cluster of NVIDIA A100/A6000 GPUs |
|
| 43 |
-
| Compute time | ~3-4 hours | Many GPU-days |
|
| 44 |
-
| Cost | $0 | Thousands of dollars |
|
| 45 |
-
| Outcome | Claim 1 verified (toy scale, real evidence); Claim 4 toy result + infrastructure validated, full comparison not completed; Claims 2-3, 5-6 not attempted |
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "artifact", "id": "cell_8088718eab2b", "created_at": "2026-08-03T02:23:47+00:00", "title": "Reproduction bundle (environment, surrogate, validation script, C++ patch)", "artifact": "nonzero-repro/repro-bundle:v1", "artifact_type": "dataset"}
|
| 7 |
-->
|
| 8 |
**📦 Artifact** `nonzero-repro/repro-bundle:v1` · dataset
|
| 9 |
|
| 10 |
trackio-artifact://nonzero-repro/repro-bundle:v1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/executive-summary/page.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
Partial reproduction of NonZero. Of the paper's 6 claims, Claim 1's core mathematical formulation was verified exactly (finite-difference identity holds to floating-point precision), and the surrogate model was shown to learn true reward structure at its theoretical noise ceiling (R2=0.90) on a toy-scale test. Claim 4's supporting infrastructure (environment, baseline training pipeline, and a compiling but not-yet-wired C++ patch for NonUCT) was built and validated at the component level, but no end-to-end NonZero-vs-baseline comparison was completed, so Table 1's reported numbers were neither reproduced nor falsified. Claims 2-3 (theoretical proofs) and Claims 5-6 (SMAC/SMACv2) were not attempted: the former due to time constraints, the latter because the paper's own training recipe requires A100-class GPU hardware unavailable on free-tier compute. All work was done on a single Kaggle T4 GPU, free tier, over approximately 3 hours.
|
| 9 |
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_68176da7105c", "created_at": "2026-08-03T02:23:48+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-08-03T02:23:48+00:00"}
|
| 7 |
-->
|
| 8 |
Partial reproduction of NonZero. Of the paper's 6 claims, Claim 1's core mathematical formulation was verified exactly (finite-difference identity holds to floating-point precision), and the surrogate model was shown to learn true reward structure at its theoretical noise ceiling (R2=0.90) on a toy-scale test. Claim 4's supporting infrastructure (environment, baseline training pipeline, and a compiling but not-yet-wired C++ patch for NonUCT) was built and validated at the component level, but no end-to-end NonZero-vs-baseline comparison was completed, so Table 1's reported numbers were neither reproduced nor falsified. Claims 2-3 (theoretical proofs) and Claims 5-6 (SMAC/SMACv2) were not attempted: the former due to time constraints, the latter because the paper's own training recipe requires A100-class GPU hardware unavailable on free-tier compute. All work was done on a single Kaggle T4 GPU, free tier, over approximately 3 hours.
|
| 9 |
|
workspace.json
CHANGED
|
@@ -3,22 +3,6 @@
|
|
| 3 |
"file_count": 0,
|
| 4 |
"total_size": 0,
|
| 5 |
"files": [],
|
| 6 |
-
"hub_refs": [
|
| 7 |
-
{
|
| 8 |
-
"url": "https://huggingface.co/jobs/byte-vortex/6a6ff4e06b79c09949c200e0",
|
| 9 |
-
"type": "Jobs",
|
| 10 |
-
"label": "byte-vortex/6a6ff4e06b79c09949c200e0"
|
| 11 |
-
},
|
| 12 |
-
{
|
| 13 |
-
"url": "https://huggingface.co/jobs/byte-vortex/6a6ff5736b79c09949c200e4",
|
| 14 |
-
"type": "Jobs",
|
| 15 |
-
"label": "byte-vortex/6a6ff5736b79c09949c200e4"
|
| 16 |
-
},
|
| 17 |
-
{
|
| 18 |
-
"url": "https://huggingface.co/buckets/byte-vortex/nonzero-repro-artifacts",
|
| 19 |
-
"type": "Buckets",
|
| 20 |
-
"label": "byte-vortex/nonzero-repro-artifacts"
|
| 21 |
-
}
|
| 22 |
-
],
|
| 23 |
"reference_only": true
|
| 24 |
}
|
|
|
|
| 3 |
"file_count": 0,
|
| 4 |
"total_size": 0,
|
| 5 |
"files": [],
|
| 6 |
+
"hub_refs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
"reference_only": true
|
| 8 |
}
|