A Hamiltonian with finite entries whose differences overflow is accepted, and the resulting Liouvillian contains non-finite entries. Nothing after the build checks that the generator is finite.
Reproduction (origin/main, 38f8652 lineage; checked 2026-09-11)
import numpy as np
from liouscope.core.lindblad import build_liouvillian
H = np.diag([1e308, -1e308]).astype(complex)
L = build_liouvillian(H, [])
np.all(np.isfinite(L)) # False — accepted without error
Control: diag(1, -1) is accepted and L is finite, so the probe discriminates.
Why it gets through
The Hermiticity gate works on the gauge-fixed scale of H, which is finite here. But the coherent part -i[H, ·] contains the diagonal differences H_jj − H_kk = 2e308, and those overflow. So the gate checks the input, and nobody checks the output.
Found while reviewing PR #127, where the reviewer (Equalita) and the author (Codie) reproduced it independently. It also happens on main, so it is not caused by #127 and should be fixed separately.
Suggested fix
After building, check np.all(np.isfinite(L)) (dense) or np.all(np.isfinite(L.data)) (sparse). Reject with the same error family as the other non-representable-input guards. Tests should cover:
- a before-test on the case above;
- a control that must stay accepted;
- both builders.
Related
A Hamiltonian with finite entries whose differences overflow is accepted, and the resulting Liouvillian contains non-finite entries. Nothing after the build checks that the generator is finite.
Reproduction (origin/main, 38f8652 lineage; checked 2026-09-11)
Control:
diag(1, -1)is accepted andLis finite, so the probe discriminates.Why it gets through
The Hermiticity gate works on the gauge-fixed scale of
H, which is finite here. But the coherent part-i[H, ·]contains the diagonal differencesH_jj − H_kk = 2e308, and those overflow. So the gate checks the input, and nobody checks the output.Found while reviewing PR #127, where the reviewer (Equalita) and the author (Codie) reproduced it independently. It also happens on
main, so it is not caused by #127 and should be fixed separately.Suggested fix
After building, check
np.all(np.isfinite(L))(dense) ornp.all(np.isfinite(L.data))(sparse). Reject with the same error family as the other non-representable-input guards. Tests should cover:Related