Skip to content

Commit 9e5a0cc

Browse files
committed
fix(ci): keep CategoricalRelaxation forward bit-identical for the typical positive case
The previous defensive ``x.clamp(min=1e-8)`` before normalisation slightly shifted the simplex output even when ``x`` was already safe, which was enough to break ``test_smoke.py::test_coloring_cpu`` (K=2, 200 epochs) on CI across Python 3.10 / 3.11 / 3.12. Guard *only* the denominator so the typical case is identical to the historical implementation, and the NaN/Inf failure mode (``x.sum`` ~ 0) is still defended against. Also bump deprecated GitHub Actions to silence the Node.js 20 deprecation warning in CI: ``actions/checkout@v4 -> v5``, ``astral-sh/setup-uv@v3 -> v8``. Made-with: Cursor
1 parent 629ce97 commit 9e5a0cc

2 files changed

Lines changed: 9 additions & 8 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414
matrix:
1515
python-version: ["3.10", "3.11", "3.12"]
1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@v5
1818

1919
- name: Install uv
20-
uses: astral-sh/setup-uv@v3
20+
uses: astral-sh/setup-uv@v8
2121
with:
2222
enable-cache: true
2323

src/qqa/relaxation.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,13 @@ def init(self, sol_size, problem, device):
179179
)
180180

181181
def forward(self, x):
182-
# AdamW can push ``x`` negative / very close to zero, so the raw
183-
# ``x / x.sum`` normalisation can blow up (NaN / Inf). Clamp to a
184-
# small positive floor before dividing; the normalisation still
185-
# yields a proper simplex and the discrete projection is unchanged.
186-
x_pos = x.clamp(min=1e-8)
187-
return x_pos / x_pos.sum(dim=2, keepdim=True)
182+
# ``x / x.sum`` is the normal simplex normalisation. The only failure
183+
# mode is the (rare) pathological case where the sum across categories
184+
# becomes ~0 or negative, which would produce NaN/Inf and corrupt the
185+
# AdamW state. Guard *only* the denominator so the typical positive
186+
# case is bit-for-bit identical to the historical implementation.
187+
s = x.sum(dim=2, keepdim=True)
188+
return x / s.clamp(min=1e-8)
188189

189190
def project(self, x):
190191
idx = torch.argmax(x, dim=2)

0 commit comments

Comments
 (0)