Skip to content

Linear algebra functions for fermions#732

Merged
pcchen merged 25 commits into
masterfrom
fermions
May 30, 2026
Merged

Linear algebra functions for fermions#732
pcchen merged 25 commits into
masterfrom
fermions

Conversation

@manuschneider
Copy link
Copy Markdown
Collaborator

@manuschneider manuschneider commented Dec 10, 2025

All linear algebra functions that accept BlockUniTensor or LinOp work with fermions. This affects:
Eig, Eigh, Gesvd_truncate, Qr, ExpH, ExpM, Arnoldi, Lanczos, Lanczos_Gnd_Ut.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 10, 2025

Codecov Report

❌ Patch coverage is 37.55102% with 306 lines in your changes missing coverage. Please review.
✅ Project coverage is 29.58%. Comparing base (9de1207) to head (229f7a8).
⚠️ Report is 29 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/linalg/Gesvd_truncate.cpp 30.00% 11 Missing and 38 partials ⚠️
src/linalg/Svd_truncate.cpp 33.33% 10 Missing and 34 partials ⚠️
src/linalg/Qr.cpp 27.27% 15 Missing and 17 partials ⚠️
src/linalg/Eigh.cpp 45.23% 1 Missing and 22 partials ⚠️
src/linalg/Gesvd.cpp 41.02% 1 Missing and 22 partials ⚠️
src/linalg/Svd.cpp 42.50% 3 Missing and 20 partials ⚠️
src/linalg/Eig.cpp 47.61% 1 Missing and 21 partials ⚠️
src/linalg/ExpM.cpp 39.28% 5 Missing and 12 partials ⚠️
src/linalg/ExpH.cpp 44.00% 3 Missing and 11 partials ⚠️
src/linalg/Lanczos.cpp 43.47% 0 Missing and 13 partials ⚠️
... and 8 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #732      +/-   ##
==========================================
+ Coverage   27.90%   29.58%   +1.67%     
==========================================
  Files         241      213      -28     
  Lines       35470    30474    -4996     
  Branches    14778    12012    -2766     
==========================================
- Hits         9898     9015     -883     
+ Misses      18591    16656    -1935     
+ Partials     6981     4803    -2178     
Flag Coverage Δ
cpp 29.58% <37.55%> (+2.08%) ⬆️
python ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@manuschneider manuschneider marked this pull request as ready for review April 22, 2026 11:37
@manuschneider manuschneider added the Pending check/approval Issue fixed, and need feedback label Apr 22, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ca1b01b1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Eig.cpp
Comment thread src/linalg/Eig.cpp
}
std::vector<Tensor> blks;
// std::cout<<out[1];
algo::Vsplit_(blks, out[1], split_dims);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Respect row_v when rebuilding fermionic eigenvector blocks

The fermionic reconstruction always does Vsplit_ on out[1] using row-block sizes, which only matches the column-vector layout. In the !row_v branch of tensor Eig, eigenvectors are returned in row form, so splitting on rows assigns qindices/reshapes along the wrong axis and produces incorrect eigenvector block structure (this affects the default row_v value). The split/remap logic needs to branch on row_v (and the same issue appears in the copied fermionic Eigh code).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bug in Eig and Eigh that already existed for BlockUniTensor. I created a new issue for it, see #782. For now, I throw an error message if !row_v.

@IvanaGyro
Copy link
Copy Markdown
Collaborator

How about to ask AI to create some tests which also cover the problem that AI pointed out?

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7deb36534

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Eig.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 900ee1a9f4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Eig.cpp
Comment thread src/linalg/Eigh.cpp Outdated
Copy link
Copy Markdown
Collaborator

@pcchen pcchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted by Claude Code on behalf of @pcchen

PR #732 Review: Linear algebra functions for fermions

Overview

This PR implements Eig, Eigh, Gesvd_truncate, and Qr for BlockFermionicUniTensor, completing fermionic support for these core linalg operations. It also includes widespread cleanup across all linalg files: removing using namespace std, renaming internal helpers to static functions with _internal suffixes, removing split namespace blocks, and improving error messages uniformly.


Correctness

Core fermionic logic (sign-flip handling):

  • The sign-flip approach in all four new _BlockFermionic_UT_internal functions is consistent: blocks with signflip[b] == true are negated (Tlist[i] = -Tlist[i]) before being assembled into the big block matrix. This matches the pattern established in the existing Gesvd implementation. The approach is correct for Hermitian/symmetric matrices (Eigh) since negating a block still yields a Hermitian block.
  • For general Eig (non-Hermitian case), negating a row-block before assembly is also correct.

Output _signflip always set to false:

  • In Eig_BlockFermionic_UT_internal, Eigh_BlockFermionic_UT_internal, and Qr_BlockFermionic_UT_internal, the output eigenvector/Q/R matrices are created with _signflip = std::vector(v_blocks.size(), false). This is correct because the sign has already been absorbed into the numerical values, so the returned UniTensors carry no pending sign-flip.

Potential issue — Eig with is_V=true, column index into v_itoi:

In Eig_BlockFermionic_UT_internal, the is_V branch does:

v_itoi.back()[Tin.rowrank()] = e_blocks.size() - 1;
v_itoi.back().resize(Tin.rowrank() + 1);

v_itoi.back() is populated from Tin.get_qindices(...), which has Tin.rank() elements. The assignment [Tin.rowrank()] sets the aux-bond index, and resize truncates to rowrank + 1. This mirrors Eig_Block_UT_internal exactly, so it appears correct — but worth verifying that Tin.get_qindices(b) returns a copy (not a reference that would mutate the original tensor's index table).

Gesvd_truncate: merging Block and BlockFermionic paths:

  • The old _gesvd_truncate_BlockFermionic_UT and _gesvd_truncate_Block_UT are replaced by a single Gesvd_truncate_Block_UTs_internal that handles both by checking Tin.uten_type() == UTenType.BlockFermionic when calling vec_erase_(...signflip_...). This is clean and reduces duplication significantly.
  • The to_be_removed.empty() guard added around all vec_erase_ calls is a genuine bug fix — previously this would call vec_erase_ with an empty list on every pass.

Code Quality

Positive changes:

  • Removing using namespace std and replacing with std:: qualifiers throughout — good hygiene.
  • Renaming _Eig_Dense_UTEig_Dense_UT_internal (with static) is better practice than the leading-underscore naming convention.
  • Collapsing double namespace cytnx { namespace linalg { ... } } patterns into single nested blocks.
  • Improving error messages with actual values (rank is %d) rather than just descriptions.

Issues and suggestions:

  1. Significant code duplication. Eig_BlockFermionic_UT_internal and Eigh_BlockFermionic_UT_internal are near-identical; the only difference is the call to linalg::Eig vs linalg::Eigh. Similarly, Qr_BlockFermionic_UT_internal duplicates the block-combination boilerplate. The PR does add "Exactly the same as ... with Eig() → Eigh()" comments which is helpful, but the duplicated code is a maintenance burden going forward.

  2. Leftover commented-out debug code. Several places retain commented-out std::cout statements and dead code:

    • Eig.cpp / Eigh.cpp: // std::cout << BdLeft << std::endl;, // std::cout << strides << std::endl;, etc.
    • Eig.cpp is_V block: // std::cout << out[tr].shape() << std::endl; — note tr isn't declared in that scope (copy-paste artifact from Gesvd), harmless since it's in a comment but worth removing.
    • Commented-out alternatives like // Tlist[i] = Tlist[i].Mul(-1); and stubs like // vec2d<cytnx_uint64> vT_itoi; should be removed.
  3. Rsvd_truncate.cpp residual };:

    };  // Rsvd_truncate_Dense_UT_internal

    The trailing semicolon after } is harmless but inconsistent with how all other functions were cleaned up in this PR. Minor.

  4. resize after assignment in v_itoi: In both Eig and Eigh fermionic internals, resize is called after writing to v_itoi.back()[Tin.rowrank()]. This is correct since rowrank < rank is validated, but the order (write then truncate) is slightly fragile. Resizing first and then assigning would be clearer.


Test Coverage

  • Two new error-case tests (err_rowrank_equal_rank_dense_UT) added for Svd and Gesvd — good.
  • Two new Eig/Eigh row-v tests added in linalg_test.cpp.
  • Missing: No tests exercise the new fermionic code paths (Eig_BlockFermionic_UT_internal, Eigh_BlockFermionic_UT_internal, Qr_BlockFermionic_UT_internal) directly. Given the complexity of sign-flip handling, at minimum one round-trip correctness test for each new fermionic function would be valuable before merge.

Summary

The core logic is sound and the cleanup is a genuine improvement. Main asks before merge:

  1. Remove dead/commented-out debug code.
  2. Add at least basic fermionic round-trip tests for the newly implemented functions.
  3. (Minor) Fix the residual }; in Rsvd_truncate.cpp.

@manuschneider
Copy link
Copy Markdown
Collaborator Author

Cleaned up the code and included suggestions. Could someone use AI support to write unit tests?

@ianmccul
Copy link
Copy Markdown
Collaborator

You can probably directly ask @codex to write the tests?

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Added regression coverage for BlockUniTensor eigenvalue-only calls so linalg::Eig(..., is_V=false, row_v=true) and linalg::Eigh(..., is_V=false, row_v=true) are explicitly tested to succeed.
  • Added BlockFermionic edge-case tests covering both: (1) argument validation for rowrank == rank in Eig/Eigh, and (2) eigenvalue-only (is_V=false) behavior with row_v=true for both routines.
  • Updated the block and block-fermionic Eig guards so row_v=true is rejected only when eigenvectors are requested (is_V && row_v), preventing regressions in eigenvalue-only calls.
  • Applied the same guard fix for Eigh in both block and block-fermionic paths.
  • Committed on branch work with commit fb540776, and created a follow-up PR via the make_pr tool.

Testing

  • ⚠️ cmake -S . -B build -DBUILD_TESTS=ON (configuration failed in this environment due to missing Boost CMake package files: BoostConfig.cmake / boost-config.cmake).

View task →

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6677eb80e3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Eig.cpp Outdated
@manuschneider manuschneider removed the Pending check/approval Issue fixed, and need feedback label May 26, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f0e8fbe11

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Eig.cpp
Comment thread src/linalg/Eigh.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 765173a083

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Svd.cpp Outdated
@pcchen
Copy link
Copy Markdown
Collaborator

pcchen commented May 29, 2026

Issue Status Check

Posted by Claude Code on behalf of @pcchen

Here's the current status of each raised issue:


Issue 1 — P1: Guard BlockFermionic Eig against missing column bond

RESOLVED. Fixed in commit 0f64e0f per author's reply. The current code validates bounds before entering the block path.

Issue 2 — P1: Respect row_v when rebuilding fermionic eigenvector blocks

ACKNOWLEDGED / DEFERRED. Author created #782 to track the underlying bug. The current code guards with cytnx_error_msg(row_v && is_V, ...), so the default path (row_v=false) works. The unsupported row_v=true path now throws a clear error instead of producing wrong results.

Issue 3 — P1: Restore default row_v path for block eigendecompositions

RESOLVED. The guard is now row_v && is_V — default calls (row_v=false) pass through without error.

Issue 4 — P2: Gate row_v validation on is_V in block Eig

RESOLVED. The guard row_v && is_V means eigenvalue-only calls (is_V=false) are unaffected regardless of row_v.

Issue 5 — P2: Gate row_v validation on is_V in block Eigh

RESOLVED. Same row_v && is_V guard applied in Eigh_BlockUT_internal.

Issue 6 — P1: Preserve complex dtype for fermionic Eig eigenvalues

DISPUTED / UNVERIFIED. The bot flagged Type.Double in e_ptr->Init(...). Author responded that dtype is a dummy since e_ptr->_blocks = e_blocks overwrites it. A comment was added to the code to document this. This defence is plausible but relies on internal BlockFermionicUniTensor block-assignment behaviour propagating dtype correctly — worth a targeted test to confirm.

Issue 7 — P1: Avoid forwarding eigenvalue-only fermionic Eig to Tensor Eig

RESOLVED. The Tensor::Eig implementation now explicitly leaves V as a void tensor when is_V=false, and the backend detects void storage to skip eigenvector computation. A comment was added to document this contract.

Issue 8 — P1: Avoid forwarding eigenvalue-only fermionic Eigh to Tensor Eigh

RESOLVED. Same pattern as Issue 7, same comment added.

Issue 9 — P2: Use input device for dense singular-value tensors

RESOLVED. Cy_S.Init now uses outT[t].dtype(), outT[t].device() instead of the hardcoded Device.cpu.


Summary: 8 of 9 issues are resolved. Issue 6 (complex dtype) is the only open question — the author's response is plausible but the behaviour is untested. A unit test computing Eig on a BlockFermionicUniTensor with a non-Hermitian block (so eigenvalues have non-zero imaginary parts) and checking the result is complex would close this definitively.

@pcchen
Copy link
Copy Markdown
Collaborator

pcchen commented May 29, 2026

@manuschneider Can you double check if you have fix Issue 6 (complex dtype). I will approve and merge after you verify this.

@manuschneider
Copy link
Copy Markdown
Collaborator Author

@manuschneider Can you double check if you have fix Issue 6 (complex dtype). I will approve and merge after you verify this.

The Init functions of Dense and non-Dense are inconsistent and check different things, so only the Dense path failed.

I changed the dtype and device in all paths to be consistent with the data it will be filled with, so the implementation becomes independent of the put_block implementation and its checks.

So this is resolved now.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3217bd69f5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/ExpM.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef94d4b8fe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Lanczos.cpp
Comment thread src/linalg/Arnoldi.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8590b4937f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Arnoldi.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 023eaf3dc4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Svd.cpp
"[ERROR][Svd] Input UniTensor should have rowrank>0, but rowrank is %d\n",
Tin.rowrank());
cytnx_error_msg(
Tin.rowrank() >= Tin.rank(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow dense SVD with a scalar column space

Because this validation runs before dispatching on the UniTensor type, dense UniTensors with rowrank == rank now fail even though the previous dense path supported them by reshaping the data to a (prod(row dims) x 1) matrix and calling the Tensor SVD. This is a user-visible regression for dense tensors whose rowrank intentionally places all physical legs on the row side; the new rowrank < rank guard is needed for the block implementation's column-bond access, but should not reject the dense case.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If rowrank == rank, the return is U = normalized vector, S norm of vector, V trivial one-element tensor.

I do not think that users should call SVD to normalize a vector. This was possible only in the dense branch. If we allow it, we should do this everywhere. But I would keep it as is, because running SVD on a vector instead of a matrix is most likely not intended by the user; it's more likely a bug in their code logic. And if it is intended, it can easily be replaced by dividing by the norm (which is cleaner code as well).

@manuschneider
Copy link
Copy Markdown
Collaborator Author

All linear algebra functions that previously accepted either BlockUniTensor or LinOp now work with fermionic tensors/operators. Changes are tested on CPU and GPU. Previous issues are all addressed.

This PR is ready for a final review.

@manuschneider manuschneider added the Pending check/approval Issue fixed, and need feedback label May 29, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 546a3f4566

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Lanczos.cpp
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 229f7a805d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/linalg/Svd.cpp
@pcchen
Copy link
Copy Markdown
Collaborator

pcchen commented May 30, 2026

Issue Status Check

Posted by Claude Code on behalf of @pcchen

Here is the current status of all raised issues:


P1 Issues

Issue Status
Guard BlockFermionic Eig against missing column bond ✅ Fixed in 0f64e0f
Restore default row_v path for block eigendecompositions ✅ Fixed
Avoid forwarding eigenvalue-only fermionic Eig to Tensor Eig ✅ Resolved — internal _impl null check handles it (comment added)
Avoid forwarding eigenvalue-only fermionic Eigh to Tensor Eigh ✅ Resolved — same as above
Preserve complex dtype for fermionic Eig eigenvalues ✅ Resolved — dtype is a dummy; blocks are overwritten
Respect row_v when rebuilding fermionic eigenvector blocks ⏩ Deferred to #782 — now throws a clear error instead of producing wrong results
Initialize fermionic signflips for Svd value tensors ✅ Not an issue — _signflip is initialized correctly in BlockFermionicUniTensor::Init even with no_alloc=true

P2 Issues

Issue Status
Gate row_v validation on is_V in block Eig ✅ Fixed
Gate row_v validation on is_V in block Eigh ✅ Fixed
Use input device for dense singular-value tensors ✅ Fixed
Preserve bias term in fermionic ExpM ✅ Fixed
Clear fermionic signflips on Lanczos outputs ✅ Fixed
Clear fermionic signflips on Arnoldi outputs ✅ Fixed
Populate real BlockFermionic Arnoldi eigenvectors ✅ Fixed
Use CUDA copies for fermionic Lanczos blocks ✅ Fixed
Allow dense SVD with rowrank == rank 🚫 Won't fix — intentional; using SVD to normalize a vector is likely a user logic error

All issues are addressed. This PR is approved for merge.

@pcchen pcchen merged commit 72a508c into master May 30, 2026
8 checks passed
@pcchen pcchen deleted the fermions branch May 30, 2026 03:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Pending check/approval Issue fixed, and need feedback Top priority The Issue that has top priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants