Skip to content

Conversation

@Yue-Zhengyuan
Copy link
Member

This PR makes SUWeight axis order independent of the virtual arrow directions of the matching iPEPS/O. They are now always (west, east) or (south, north).

I managed to keep weight elements positive by requiring that the weights are absorbed into the site tensors without twists. It may be better now to mentally regard each weight as a tuple (bond space, SVD spectrum vector), only stored as a DiagonalTensorMap for convenience.

I still prefer saving the SUWeight as the environment of the bra-ket norm network, at the (very minor) cost that we need to take square roots when absorbing/removing weights from iPEPS/O tensors. In this way, the relation to CTMRGEnv and BP is most manifest.

@Yue-Zhengyuan Yue-Zhengyuan requested a review from lkdvos December 12, 2025 09:57
@codecov
Copy link

codecov bot commented Dec 12, 2025

Codecov Report

❌ Patch coverage is 93.75000% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/algorithms/truncation/bond_truncation.jl 0.00% 2 Missing ⚠️
src/environments/suweight.jl 96.61% 2 Missing ⚠️
Files with missing lines Coverage Δ
src/PEPSKit.jl 100.00% <ø> (ø)
src/algorithms/time_evolution/evoltools.jl 96.15% <100.00%> (+0.96%) ⬆️
src/algorithms/time_evolution/simpleupdate3site.jl 100.00% <100.00%> (ø)
src/utility/util.jl 70.83% <100.00%> (+1.44%) ⬆️
src/algorithms/truncation/bond_truncation.jl 94.73% <0.00%> (ø)
src/environments/suweight.jl 90.25% <96.61%> (+1.60%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Yue-Zhengyuan
Copy link
Member Author

Hold on, just found a problem in CTMRGEnv(wts). Will fix it soon.

@Yue-Zhengyuan
Copy link
Member Author

Well, it turns out to be bugs in external code not relevant to contents in this PR...

Comment on lines +36 to +37
# contract local ⟨t|t⟩ without virtual twists
@tensor ρ[k; b] := conj(t[b; n e s w]) * twistdual(t, 2:5)[k; n e s w]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# contract local ⟨t|t⟩ without virtual twists
@tensor ρ[k; b] := conj(t[b; n e s w]) * twistdual(t, 2:5)[k; n e s w]
# contract local ⟨t|t⟩ without virtual twists
@plansor ρ[k; b] := conj(t[b; n e s w]) * t[k; n e s w]

But this is also just t' * t

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, it is not t' * t (this is contracting the physical legs), or t * t' (is this what you actually mean?). The reason is a bit subtle (and also related to discussions in #283 about why all reduced density matrices (RDMs) are normalized with supertraces).

The matrix element of an operator O x 1 between two states |bra>, |ket> (assuming all physical spaces are non-dual for simplicity) is <bra|O x 1|ket>, where O acts on a sub-system, while 1 acts on the other parts. PEPSKit constructs the RDM for O as O -> <bra|_ x 1|ket>, but then decides to permute (instead of transpose, because of the usage of @tensor) the ket axes to the front to follow the traditional axis order for RDMs.

Before the final permutation, the RDM is something like $\rho_{ab} \bra{a} \ket{b}$, where $\rho_{ab}$ is positive-definite. It is normalized with the ordinary trace.

But afterwards it becomes (for fermions) ${({-1})}^{{|a|}{|b|}} \rho_{ab} \ket{b} \bra{a}$. The new matrix $\tilde{\rho}{ba} = {({-1})}^{{|a|}{|b|}} \rho{ab}$ is no longer positive definite, and is normalized with supertrace to cancel the twist introduced by permute.

Therefore, the RDM should be ρ = twist(t * t', numout(t)). If you think this is better, please just go ahead to change it (I tested and it works).

Copy link
Member

Choose a reason for hiding this comment

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

You are completely right, I overlooked that it really has to be t * t' to make the correct legs contracted, but I'm slightly lost again with what comes after.

In order for the leg order to be consistent, should it not be transpose(t * t'), which would be what the @plansor call evaluates to? Are you then suggesting we need an additional twist to compensate for the twist we will be adding in the normalization through the supertrace, or would this then not need a twist at all?

@Yue-Zhengyuan Yue-Zhengyuan requested a review from lkdvos December 22, 2025 11:01

"""
SUWeight(Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:Union{Int,ElementarySpace}}}
SUWeight(Nspaces::M, [Espaces::M]; random::Bool=false) where {M<:AbstractMatrix{<:ElementarySpace}}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not entirely convinced that the random keyword is appropriate for the constructor here. We could also just define rand!(::SUWeight) instead if this is useful functionality, rather than trying to fit everything in the constructor call?
I'm mostly saying this since it feels slightly arbitrary to include Inf-normalized uniformly distributed random elements as the only option, while we could also have randexp etc. Putting all of these configurations through keyword arguments usually ends up slightly messy

Copy link
Member Author

Choose a reason for hiding this comment

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

I now introduced Random.rand! without normalization as you suggested.

Copy link
Member

@lkdvos lkdvos left a comment

Choose a reason for hiding this comment

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

Sorry for taking a while, I left some minor comments but otherwise this looks good to go for me!

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.

2 participants