sbd_solver: populate SCIResult.rdm1/rdm2 from SBD's computed RDMs - #36
Merged
Merged
Conversation
SBD's C++ layer already computes real one_p_rdm/two_p_rdm whenever
do_rdm=1 is requested (sbdiag.h's do_rdm != 0 branch), and bindings.cpp
already returns them in the results dict -- but _solve_sci_core never
read those two keys, so every SCIResult silently left rdm1/rdm2 at their
None default even when a caller asked for RDMs.
The reshape/transpose in the new _assemble_rdms helper is not a guess:
verified against PySCF's own make_rdm1/make_rdm2 on a small fixed H2O
subspace, on all three SBD backends (cpu, gpu-thrust, gpu-omp-offload) --
both element-wise on the full tensors and via the energy identity
E = einsum("pr,pr->",rdm1,hcore) + 0.5*einsum("prqs,prqs->",rdm2,eri)
that SCIResult.rdm1/rdm2 are contracted with everywhere else in
qiskit-addon-sqd. All three backends agreed to machine precision.
do_rdm=0 (the default, used by both run_sqd_sbd.py and
run_sqd_enlarge_subspace_sbd.py) is unaffected: rdm1/rdm2 stay None,
exactly as before.
This is plumbing only, verified against a hand-built tiny subspace, not a
new driver -- an orbital-optimization driver using these RDMs with
rotate_integrals/optimize_orbitals is a separate follow-on.
Sophia Wen (hfwen0502)
force-pushed
the
sbd-rdm
branch
from
September 17, 2026 22:22
281bb2f to
7944496
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sbd_solver.py's_solve_sci_corecallsbackend.tpb_diag(...), which(per
bindings.cpp) always returnsresults["one_p_rdm"]andresults["two_p_rdm"]in its dict — populated with real data wheneversbd_config["do_rdm"]is set to 1._solve_sci_corereadresults["energy"]/results["density"]but never readone_p_rdm/two_p_rdm— everySCIResultit returned leftrdm1/rdm2at their dataclass default of
None, even when a caller explicitlyrequested RDMs. SBD computed real RDMs and the wrapper threw them away.
assemble_rdms(results, norb)(public — used by more than just thismodule now) that reshapes SBD's raw flat arrays into
rdm1(norb,norb)/
rdm2(norb,norb,norb,norb)and wires it intosolve_sci/solve_sci_batch's returnedSCIResult.(None, None)whendo_rdmwas 0 (the default) — no behaviorchange for existing callers that don't request RDMs.
Verification
The reshape/transpose is not a guess — verified by hand against PySCF's
own
make_rdm1/make_rdm2on a fixed subspace, on all three SBDbackends (cpu, gpu-thrust, gpu-omp-offload):
E = einsum("pr,pr->",rdm1,hcore) + 0.5*einsum("prqs,prqs->",rdm2,eri)reproduces the solver's own reportedenergy to machine precision (~1e-14) on all three backends.
No automated regression test is included for this specific reshape
formula — an earlier version of this PR had one, but it depended on
pyscf/qiskit-addon-sqd, neither of which is in this project'stestextras (only
notebook-dependencies), so it broke CI collection. A futureregression here would also surface immediately and visibly through
run_sbd_diag.py's--rdmoutput (trace ofrdm1, natural orbitaloccupations) in #37.
Test plan
solve_scipath(not just the raw bindings) on H2O, on all three backends —
trace(rdm1)matches the electron count, energy-from-RDMs matchesthe solver's own energy to ~1e-14.
do_rdm=0(default) confirmed unaffected —rdm1/rdm2stayNone.