Skip to content

Add Neighborhood Tensor Update (NTU)#144

Draft
Yue-Zhengyuan wants to merge 64 commits into
QuantumKitHub:mainfrom
Yue-Zhengyuan:bondenv-ntu
Draft

Add Neighborhood Tensor Update (NTU)#144
Yue-Zhengyuan wants to merge 64 commits into
QuantumKitHub:mainfrom
Yue-Zhengyuan:bondenv-ntu

Conversation

@Yue-Zhengyuan

@Yue-Zhengyuan Yue-Zhengyuan commented Feb 27, 2025

Copy link
Copy Markdown
Member

(Finally, after being delayed for over a year)


This PR adds the Neighborhood Tensor Update (NTU, arXiv 2107.06635), which works for both iPEPS and iPEPO, and supports nearest neighbor 2-site gates and arbitrary MPO gates (in particular, the next-nearest neighbor 3-site MPO).

One caveat to be emphasized is that after applying an N-site gate (N > 2), the updated bonds are truncated sequentially without going back. In other words, it does not perform an ALS optimization of all site tensors that are updated, since producing the environment surrounding a general cluster of sites is complicated, and the following ALS optimization will be extremely costly.

When truncating a bond after applying a time evolution gate, the NTU uses some neighboring tensors as the bond environment, instead of using only a few bond weights (simple update) of the full iPEPS approximated by CTM (full update), "interpolating" between the two extremes. Currently the NN, NN+ and NNN bond environments (see description in the YASTN package) are implemented.

@codecov

codecov Bot commented Feb 27, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 28.35052% with 278 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/algorithms/time_evolution/ntupdate.jl 0.00% 122 Missing ⚠️
src/algorithms/time_evolution/ntupdate3site.jl 0.00% 73 Missing ⚠️
src/algorithms/truncation/bond_tensor.jl 0.00% 34 Missing ⚠️
src/algorithms/time_evolution/get_cluster.jl 51.72% 14 Missing ⚠️
src/algorithms/time_evolution/apply_mpo.jl 0.00% 13 Missing ⚠️
src/algorithms/contractions/bondenv/gaugefix.jl 33.33% 8 Missing ⚠️
src/algorithms/time_evolution/simpleupdate3site.jl 33.33% 6 Missing ⚠️
src/algorithms/contractions/bondenv/benv_tools.jl 87.50% 5 Missing ⚠️
src/algorithms/time_evolution/simpleupdate.jl 81.81% 2 Missing ⚠️
src/utility/util.jl 83.33% 1 Missing ⚠️
Files with missing lines Coverage Δ
src/algorithms/contractions/bondenv/benv_ntu.jl 100.00% <100.00%> (ø)
src/utility/util.jl 69.69% <83.33%> (+0.87%) ⬆️
src/algorithms/time_evolution/simpleupdate.jl 86.33% <81.81%> (-10.78%) ⬇️
src/algorithms/contractions/bondenv/benv_tools.jl 88.63% <87.50%> (+38.63%) ⬆️
src/algorithms/time_evolution/simpleupdate3site.jl 12.00% <33.33%> (-73.42%) ⬇️
src/algorithms/contractions/bondenv/gaugefix.jl 80.00% <33.33%> (-20.00%) ⬇️
src/algorithms/time_evolution/apply_mpo.jl 0.00% <0.00%> (-99.21%) ⬇️
src/algorithms/time_evolution/get_cluster.jl 65.85% <51.72%> (-21.65%) ⬇️
src/algorithms/truncation/bond_tensor.jl 53.84% <0.00%> (-46.16%) ⬇️
src/algorithms/time_evolution/ntupdate3site.jl 0.00% <0.00%> (ø)
... and 1 more

... and 16 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Yue-Zhengyuan
Yue-Zhengyuan marked this pull request as ready for review May 7, 2025 02:58
@Yue-Zhengyuan
Yue-Zhengyuan marked this pull request as draft May 26, 2025 03:37
@lkdvos
lkdvos force-pushed the master branch 2 times, most recently from ad4945f to 37ace4c Compare June 13, 2025 12:14
@Yue-Zhengyuan Yue-Zhengyuan changed the title Add NTU bond environments Add Neighborhood Tensor Update (NTU) Oct 24, 2025
@Yue-Zhengyuan Yue-Zhengyuan self-assigned this Nov 12, 2025
@Yue-Zhengyuan
Yue-Zhengyuan force-pushed the bondenv-ntu branch 2 times, most recently from 85d2c44 to ecbbee4 Compare November 30, 2025 01:56
@Yue-Zhengyuan Yue-Zhengyuan reopened this Apr 8, 2026
@Yue-Zhengyuan
Yue-Zhengyuan marked this pull request as ready for review April 8, 2026 08:39
@Yue-Zhengyuan

Copy link
Copy Markdown
Member Author

Some commits are based on #348, #349.

@Yue-Zhengyuan
Yue-Zhengyuan marked this pull request as ready for review June 17, 2026 07:26
@Yue-Zhengyuan

Copy link
Copy Markdown
Member Author

@lkdvos Hope to get merged soon so I can proceed from here.

@lkdvos lkdvos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry for taking so long to get to this!

function _svd_cut!(t::AbstractTensorMap)
t1, s, t2 = svd_trunc!(t; trunc = truncrank(1))
return absorb_s(t1, s, t2)
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Out of curiosity: do you need the weight to be distributed equally? Otherwise this might be replaced with left_orth!(t; trunc = truncrank(1)) or right_orth!(t; trunc = truncrank(1)), which I think removes some intermediate allocations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On a separate note, do we need this to be trivially charged for everything to work? It might reduce quite a bit of the number of legs if we can do something like:

A, B = left_orth!(t; trunc = truncspace(oneunit(spacetype(t))))
return removeunit(A, numind(A)), removeunit(B, 1)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

do you need the weight to be distributed equally?

Nice observation! Actually no, since this D = 1 leg is in the end contracted, so how we distribute s is irrelevant.

do we need this to be trivially charged for everything to work?

It seems that _svd_cut is always applied to a positive map, which then (if my feeling is right) ensures that the leading singular value has trivial charge. I'll double-check this.

In YASTN they don't need to worry about it, since they only support Abelian symmetries and allow a tensor to have nonzero total charge.

@Yue-Zhengyuan Yue-Zhengyuan Jul 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For _svd_cut! I have updated its docstring, describing a sufficient condition under which the largest singular value in the charge-neutral sector is also the largest in the entire SVD spectrum. The condition is satisfied by tensors constructed from contracting a bra-ket pair of tensors in a twist-free way, so indeed keeping the largest charge-neutral singular value works just as fine as truncrank(1).

Comment thread src/algorithms/contractions/bondenv/benv_ntu.jl Outdated
Comment thread src/algorithms/contractions/bondenv/benv_ntu.jl Outdated
Comment thread src/algorithms/contractions/bondenv/benv_ntu.jl Outdated
@assert 1 <= N <= 3 && Nh == 4 - N
open_axs = open_vaxs .+ 1
# axes to be contracted
hair_axs = Tuple(ax for ax in 2:5 if ax ∉ open_axs)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We might want to inspect the type stability on this: I think you want this to be guaranteed to be a NTuple{4 - N, Int}, since we now the open_vaxs are all in 1:4. I'm not sure the compiler is smart enough to figure that out, which presumably affects the type stability of the remainder of this function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Introduced a helper function _hair_axes for type stability.

Comment thread src/algorithms/contractions/bondenv/benv_tools.jl Outdated
Comment thread src/algorithms/contractions/bondenv/benv_tools.jl
Comment on lines +75 to +86
a, X = if stype1 == :first
bond_tensor_first(A; trunc = qrtrunc)
else
@assert stype1 == :middle
bond_tensor_midnext(A; trunc = qrtrunc)
end
b, Y = if stype2 == :last
bond_tensor_last(B; trunc = qrtrunc)
else
@assert stype2 == :middle
bond_tensor_midprev(B; trunc = qrtrunc)
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think symbols should be fine, the only other thing I can think of would be to create some @enum but I don't think it would matter in the end.

I think I follow the explanation, it seems reasonable that it is not possible to just get rid of the extra legs in the middle and that this doesn't buy us anything there.

Comment thread src/algorithms/time_evolution/simpleupdate.jl Outdated
@Yue-Zhengyuan
Yue-Zhengyuan marked this pull request as draft July 2, 2026 10:56
@Yue-Zhengyuan

Copy link
Copy Markdown
Member Author

@lkdvos I think all comments in the last review are addressed. Ready for another round of review!

@Yue-Zhengyuan
Yue-Zhengyuan requested a review from lkdvos July 16, 2026 09:01
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