microsoft / microsoft/oneqmc

Self-edges are never zeroed in MaskedMessagePassingLayer (unassigned .at[].set() is a no-op)

Open
#11 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
65
Forks
18
PR merge metrics
No merged PRs in 30d

Description

In src/oneqmc/wf/nn/masked/message_passing.py (lines 60–63):

# We will set self-edges to 0
edge_part.at[
    ..., jnp.arange(edge_part.shape[-4]), jnp.arange(edge_part.shape[-3]), :, :
].set(0.0)

JAX arrays are immutable: .at[].set() returns a new array, and here the result is discarded, so this statement is a silent no-op. Contrary to the comment, self-edges (i = j messages) are never zeroed and contribute to every message-passing update.

Minimal repro:

import jax.numpy as jnp

edge_part = jnp.ones((3, 3, 2, 4))
edge_part.at[..., jnp.arange(3), jnp.arange(3), :, :].set(0.0)
print(edge_part[0, 0].sum())   # 8.0 — unchanged

This affects MaskedMessagePassingLayer wherever it is used (the NucleiGNN and the OrbitalGenerator in Orbformer). Note that the self-edge features are not zero: the edge featurization of a zero diff vector still produces nonzero scalar features (exp(-r) = 1, sigmoid(s - r)/s), so live self-edges genuinely change the output.

Important caveat for any fix: the published LAC checkpoint was trained with this behavior, so simply adding the assignment (edge_part = edge_part.at[...].set(0.0)) would change the effective architecture and invalidate the released checkpoint. I discovered this while porting Orbformer to Apple MLX, where reproducing the checkpoint's per-geometry parameters to ~1e-6 against fp64 JAX outputs (across five geometries) required keeping self-edges live — so the shipped weights demonstrably have this baked in. The options seem to be:

  1. delete the dead statement and fix the comment, documenting that self-edges are (by accident, now by contract) part of the trained model; or
  2. apply the real fix behind a flag that defaults to the current behavior, so existing checkpoints keep working and only future training runs zero self-edges.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/oneqmc/wf/nn/masked/message_passing.py at lines 60–63 and inspect the MaskedMessagePassingLayer call sites in NucleiGNN and OrbitalGenerator. Verify the discarded JAX update and compare the behavior required by the published LAC checkpoint. Done means the selected compatibility behavior is implemented or documented consistently for existing and future models.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.