Skip to content

Test the qiskit-addon-sqd entry points, serially and under MPI - #18

Draft
garrison wants to merge 1 commit into
mainfrom
test-sqd-under-mpi
Draft

Test the qiskit-addon-sqd entry points, serially and under MPI#18
garrison wants to merge 1 commit into
mainfrom
test-sqd-under-mpi

Conversation

@garrison

@garrison garrison commented Sep 4, 2026

Copy link
Copy Markdown
Member

Nothing in the suite covered the solver wrapper that qiskit-addon-sqd is
meant to be handed. test_reference_energies goes through
tpb_diag_from_files, and the only place diagonalize_fermionic_hamiltonian
ran was run_sqd_sbd.ipynb under nbmake — which asserts nothing, so it
caught a raised exception and nothing else, on a single rank.

What this adds

test/test_sqd_integration.py, three checks each in a _standalone and an
_mpi variant sharing one body:

Test Subspace Assertion
test_small_subspace_* fixed, 40 dets energy pinned to -85.29400074571684
test_published_energy_* full 1em3 selection the published -76.23594663 (slow)
test_diagonalize_fermionic_hamiltonian_* sampled by upstream bracketed, plus shape/occupancy consistency

The first two are deterministic: the determinants are given rather than
sampled, so the answer does not depend on the process count, which is the
property worth pinning. The third runs the real self-consistent loop, so a
change to the sci_solver contract or to SCIResult/SCIState fails here
instead of in a user's script; its energy is bracketed because the subspace
comes from upstream's sampling and recovery.

All three leave fcidump_path unset, so rank 0 regenerates the FCIDUMP into
a temp dir and broadcasts the path for every rank to open — the default, what
a caller coming through diagonalize_fermionic_hamiltonian gets, and the
multi-rank path 7c7cc09 fixed.

Verified identical to ten digits on 1, 2 and 4 ranks.

Why two variants instead of one test

pytest-mpi filters on the mpi marker in opposite directions: --only-mpi
skips what is not marked, and no flag skips what is. So one function cannot
run in both modes. The bodies size the alpha-determinant grid from
MPI.COMM_WORLD, which is 1 in a single process, so the same code serves
both — tox -e py runs the _standalone variants and tox -e mpi the
_mpi ones, with no new tox env or CI plumbing needed.

bit_length

Set to 63 rather than the wrapper's default of 20. SBD fixes the packed word
count in a process-wide inline static on the first diagonalization and throws
det_vector: elem_size mismatch for any later one implying a different
count, so every test sharing a process must agree; 63 gives h2o the single
word that test_reference_energies already gets from 64.

63 is also the largest legal value. As #12 established, bitadvance()
computes (((size_t) 1) << bit_length) - 1, so 64 shifts a 64-bit size_t
by 64 — undefined behavior, reached from mpi_redistribution() and
mpi_sort_bitarray(), which is exactly what the _mpi tests exercise.

Two known gaps, both noted in the module:

  • Multi-word packing goes uncovered, and that is what a caller taking
    SBD_DEFAULT_BIT_LENGTH (20) actually gets. Covering it needs a module
    that does not share a process with these.
  • test_reference_energies still pins 64. Same UB, but on
    tpb_diag_from_files rather than the MPI paths, and out of scope here.

Not a performance question either way: at 275 determinants the solve takes
1.9s at 63 against 2.1s at 20.

Other changes

  • conftest.py: device_config and counts_path fixtures. The solver
    wrappers take a DeviceConfig rather than a backend module, so the
    "was this backend built?" skip is factored into a helper both fixtures
    call instead of being duplicated.
  • pyproject.toml: qiskit-addon-sqd and pyscf move into the test
    extra so tox -e py and tox -e mpi both cover this path. The tests
    skip themselves if the imports are unavailable.

This PR was generated by Claude Opus 5 under my guidance.

Nothing covered the solver wrapper qiskit-addon-sqd is meant to be handed.
test_reference_energies goes through tpb_diag_from_files, and the one place
diagonalize_fermionic_hamiltonian ran was run_sqd_sbd.ipynb under nbmake --
which asserts nothing, so it only ever caught a raised exception, and only
on a single rank.

Three checks, each in a _standalone and an _mpi variant sharing one body:

- solve_sci_batch over a fixed 40-determinant subspace, energy pinned. The
  determinants are given rather than sampled, so the answer is deterministic
  and the same on any process count -- which is the property worth pinning.
- The same over the full 1em3 selection, asserting the energy published in
  the vendored data. Marked slow.
- diagonalize_fermionic_hamiltonian itself, so a change to the sci_solver
  contract or to SCIResult/SCIState fails here rather than in a user script.
  Bracketed rather than pinned: the subspace comes from upstream's sampling.

All leave fcidump_path unset, so rank 0 regenerates the FCIDUMP and
broadcasts it -- the default path, and the multi-rank one 7c7cc09 fixed.

Two variants rather than one test because pytest-mpi filters on the mpi
marker in opposite directions (--only-mpi skips what is not marked, no flag
skips what is), so a single function cannot run in both modes. The bodies
size the determinant grid from MPI.COMM_WORLD, which is 1 in one process.

bit_length is 63, not the wrapper's default of 20: SBD fixes the packed word
count process-wide on the first diagonalization, so every test in a process
must imply the same one, and 63 gives the single word test_reference_energies
already gets from 64. It is also the largest legal value -- 64 shifts a
64-bit size_t by 64 in bitadvance(), which is undefined behavior on the very
paths these tests exercise (#12). That leaves multi-word packing uncovered,
which is what a default caller gets; noted in the module for a follow-up.

Verified identical to ten digits on 1, 2 and 4 ranks.

qiskit-addon-sqd and pyscf move into the test extra so tox -e py and
tox -e mpi both cover this; the tests skip if the imports are missing.

Assisted-by Claude Opus 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant