Add DUCC to qdk-chemistry - #602
Conversation
Co-authored-by: Nathan Baker <nathanbaker@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (1)
cpp/CMakeLists.txt:187
target_link_libraries()is using a$<BUILD_INTERFACE:...>generator expression for a target link item. This can stop CMake from treatingBTAS::BTASas a real target dependency (so its include dirs/usage requirements may not propagate), and it isn’t necessary here becausePRIVATEdeps are not exported anyway. Link to the target directly and keep itPRIVATEto avoid exporting it.
# Header-only and absent from public headers, so keep BTAS out of the export.
target_link_libraries(chemistry PRIVATE $<BUILD_INTERFACE:BTAS::BTAS>)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (3)
python/src/qdk_chemistry/plugins/openfermion/conversion.py:72
- The docstring describes the InteractionOperator two-body tensor as "⟨pq|sr⟩" and equates it to
(ps|qr)in chemist notation, but the implementation below constructs blocks viatranspose(0, 2, 3, 1). As written, the docstring’s index mapping doesn’t match the actual permutation used, which can mislead future maintenance/debugging.
OpenFermion defines ``h[p,q,r,s]`` via
``H₂ = ½ Σ h[p,q,r,s] a†_p a†_q a_r a_s``, which in physicist (Dirac)
notation is ``⟨pq|sr⟩``, or equivalently ``(ps|qr)`` in chemist notation.
python/src/qdk_chemistry/plugins/openfermion/conversion.py:90
- The inline comment claims the
(0, 2, 3, 1)transpose yieldsh2_so[p,q,r,s] = source[p,s,q,r]/(ps|qr), butsource.transpose(0, 2, 3, 1)actually maps tosource[p,r,s,q]. This makes the rationale internally inconsistent even if the code is correct.
# OpenFermion's InteractionOperator sums ``h[p,q,r,s] a+_p a+_q a_r a_s`` and
# the caller passes ``0.5 * h2_so``. Matching this to the electronic
# Hamiltonian ``1/2 sum_pqrs sum_st (pq|rs)_st a+_ps a+_rt a_st a_qs`` (spins
# s, t) requires each spin-orbital block to be a ``(0, 2, 3, 1)`` transpose of
# its chemist source: h2_so[p, q, r, s] = (ps|qr)_chemist = source[p, s, q, r].
cpp/include/qdk/chemistry/algorithms/effective_hamiltonian.hpp:57
- Typo in the Doxygen conditional block tag:
DOXYGEN_SUPRESSshould beDOXYGEN_SUPPRESS. As-is, Doxygen won’t recognize the directive and may emit warnings for the argument-pack documentation.
* \cond DOXYGEN_SUPRESS (Doxygen warning suppression for argument packs)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (2)
python/src/qdk_chemistry/plugins/openfermion/conversion.py:90
- The explanatory comment claims the transpose implements
h2_so[p,q,r,s] = source[p,s,q,r], buttranspose(0, 2, 3, 1)actually mapsh2_so[p,q,r,s] = source[p,r,s,q]. This mismatch makes the conversion logic hard to audit (especially given the restricted-path transpose just below). Update the comment to describe the axis reorder that the code really applies.
# OpenFermion's InteractionOperator sums ``h[p,q,r,s] a+_p a+_q a_r a_s`` and
# the caller passes ``0.5 * h2_so``. Matching this to the electronic
# Hamiltonian ``1/2 sum_pqrs sum_st (pq|rs)_st a+_ps a+_rt a_st a_qs`` (spins
# s, t) requires each spin-orbital block to be a ``(0, 2, 3, 1)`` transpose of
# its chemist source: h2_so[p, q, r, s] = (ps|qr)_chemist = source[p, s, q, r].
cpp/CMakeLists.txt:187
chemistryis created without an explicit type (add_library(chemistry)), so it can be built as STATIC whenBUILD_SHARED_LIBS=OFF. In that case, linking BTAS asPRIVATEwill not propagate BTAS to downstream link lines, which can produce unresolved symbols if BTAS is not purely header-only. Consider making the BTAS dependency PUBLIC for static builds (or otherwise ensuring downstream targets link BTAS when needed).
# Header-only and absent from public headers, so keep BTAS out of the export.
target_link_libraries(chemistry PRIVATE $<BUILD_INTERFACE:BTAS::BTAS>)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated no new comments.
Suppressed comments (1)
python/src/qdk_chemistry/plugins/openfermion/conversion.py:90
- The explanatory comment for the
(0, 2, 3, 1)transpose is internally inconsistent:transpose(0, 2, 3, 1)impliesh2_so[p, q, r, s] = source[p, r, s, q], but the comment currently statessource[p, s, q, r]. Aligning the comment with the actual mapping will avoid confusion when maintaining the OpenFermion convention logic (especially given the subtle symmetry assumptions discussed here).
# s, t) requires each spin-orbital block to be a ``(0, 2, 3, 1)`` transpose of
# its chemist source: h2_so[p, q, r, s] = (ps|qr)_chemist = source[p, s, q, r].
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (5)
python/src/qdk_chemistry/plugins/openfermion/conversion.py:109
- This inline comment describes a different index mapping than what
transpose(0, 2, 3, 1)actually assigns. Keeping the comment consistent with the code helps prevent accidental reintroduction of the non-8-fold bug this PR is addressing.
# alpha-beta block: h2_so[2p, 2q+1, 2r+1, 2s] = h2_aabb[p,s,q,r]
h2_so[e, o, o, e] = h2_aabb.transpose(0, 2, 3, 1)
cpp/CMakeLists.txt:147
chemistryis always linked againstBTAS::BTAS, but the aliasBTAS::BTASis only created in the FetchContent fallback. Iffind_package(BTAS)succeeds but provides a non-namespaced target (e.g.BTAS), the build will fail at link time. EnsureBTAS::BTASexists in both cases before using it.
find_package(BTAS QUIET)
if(NOT BTAS_FOUND)
include(FetchContent)
FetchContent_Declare(BTAS
GIT_REPOSITORY https://github.com/BTAS/btas.git
python/src/qdk_chemistry/plugins/openfermion/conversion.py:90
- The explanatory comment contradicts the actual transpose being applied.
transpose(0, 2, 3, 1)producessource[p, r, s, q], but the comment claimssource[p, s, q, r](and also references the wrong prior transpose). This makes the conversion logic hard to audit and risks future regressions.
# OpenFermion's InteractionOperator sums ``h[p,q,r,s] a+_p a+_q a_r a_s`` and
# the caller passes ``0.5 * h2_so``. Matching this to the electronic
# Hamiltonian ``1/2 sum_pqrs sum_st (pq|rs)_st a+_ps a+_rt a_st a_qs`` (spins
# s, t) requires each spin-orbital block to be a ``(0, 2, 3, 1)`` transpose of
# its chemist source: h2_so[p, q, r, s] = (ps|qr)_chemist = source[p, s, q, r].
docs/source/user/comprehensive/algorithms/index.rst:18
- The toctree lists
effective_hamiltonian_constructortwice, which can lead to duplicate entries/warnings in the built docs. Remove the duplicate entry.
effective_hamiltonian_constructor
expectation_estimator
hamiltonian_constructor
effective_hamiltonian_constructor
localizer
cpp/src/qdk/chemistry/algorithms/CMakeLists.txt:16
effective_hamiltonian.cppis listed twice intarget_sources, which can cause duplicate compilation entries/warnings and complicates build debugging. Keep only one entry.
dynamical_correlation_calculator.cpp
effective_hamiltonian.cpp
geometry_optimization.cpp
effective_hamiltonian.cpp
scf.cpp
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 25 changed files in this pull request and generated no new comments.
Suppressed comments (4)
python/src/qdk_chemistry/plugins/openfermion/conversion.py:71
- The docstring states OpenFermion uses
⟨pq|sr⟩/(ps|qr)forh[p,q,r,s], but the actual conversion in both restricted and unrestricted paths is the(0, 2, 3, 1)transpose (chemist -> physicist⟨pr|qs⟩). This inconsistency makes it hard to verify the convention and maintain the code.
OpenFermion defines ``h[p,q,r,s]`` via
``H₂ = ½ Σ h[p,q,r,s] a†_p a†_q a_r a_s``, which in physicist (Dirac)
notation is ``⟨pq|sr⟩``, or equivalently ``(ps|qr)`` in chemist notation.
python/src/qdk_chemistry/plugins/openfermion/conversion.py:92
- These comments describe the
(0, 2, 3, 1)transpose but then give an index mappingsource[p, s, q, r]that does not match whattranspose(0, 2, 3, 1)actually does (it maps tosource[p, r, s, q]). Please align the index mapping in the comment with the implemented transpose so future changes don't reintroduce the non-8-fold bug.
# Hamiltonian ``1/2 sum_pqrs sum_st (pq|rs)_st a+_ps a+_rt a_st a_qs`` (spins
# s, t) requires each spin-orbital block to be a ``(0, 2, 3, 1)`` transpose of
# its chemist source: h2_so[p, q, r, s] = (ps|qr)_chemist = source[p, s, q, r].
# (The ``(0, 3, 2, 1)`` transpose used previously only coincides with this for
# integrals with full chemist 8-fold symmetry; it silently corrupts the
python/src/qdk_chemistry/plugins/openfermion/conversion.py:108
- This alpha-beta block comment shows an index mapping (
h2_aabb[p,s,q,r]) that doesn't match the implementedtranspose(0, 2, 3, 1)(which maps toh2_aabb[p, r, s, q]). Updating the comment avoids future confusion when debugging spin-block conversions.
# alpha-beta block: h2_so[2p, 2q+1, 2r+1, 2s] = h2_aabb[p,s,q,r]
cpp/src/qdk/chemistry/algorithms/CMakeLists.txt:16
effective_hamiltonian.cppis listed twice intarget_sources, which is redundant and can lead to confusing build output or duplicate compilation in some generators. Remove the duplicate entry so the source list is unambiguous.
dynamical_correlation_calculator.cpp
effective_hamiltonian.cpp
geometry_optimization.cpp
effective_hamiltonian.cpp
scf.cpp
There was a problem hiding this comment.
🟡 Changes recommended
cpp/src/qdk/chemistry/algorithms/CMakeLists.txt lists effective_hamiltonian.cpp twice, which can break the build via duplicate compilation/linking.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 25/26 changed files
- Comments generated: 1
- Review effort level: Lite
| dynamical_correlation_calculator.cpp | ||
| effective_hamiltonian.cpp | ||
| geometry_optimization.cpp | ||
| effective_hamiltonian.cpp | ||
| scf.cpp |
Add initial DUCC implementation.
Uses BTAS code to evaluate wick-contracted BCH up to second order