Skip to content

[WIP] Environment initialization for CTMRG#264

Open
leburgel wants to merge 21 commits intomasterfrom
lb/initialize_env
Open

[WIP] Environment initialization for CTMRG#264
leburgel wants to merge 21 commits intomasterfrom
lb/initialize_env

Conversation

@leburgel
Copy link
Copy Markdown
Member

@leburgel leburgel commented Sep 26, 2025

Attempt at some better environment initialization routines for CTMRG. Should solve #255 once it's finished and documented.

This implements an initialize_environment method which initializes a CTMRGEnv for a given network according to a specific InitializationStyle. I specified three kinds of InitializationStyles: RandomInitialization for initializing a random environment, ProductStateInitialization for initializing a (potentially embedded) product state environment, and ApplicationInitialization which grows an initial environment from a product state according to a given truncation scheme. Names, arguments and which ones are optional for discussion, but at least this already handles the test case from #255 in a fairly straightforward way.

@leburgel leburgel marked this pull request as draft September 26, 2025 06:51
@codecov
Copy link
Copy Markdown

codecov bot commented Sep 26, 2025

Codecov Report

❌ Patch coverage is 65.67164% with 23 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/environments/product_state_environments.jl 54.00% 23 Missing ⚠️
Files with missing lines Coverage Δ
src/PEPSKit.jl 100.00% <ø> (ø)
src/algorithms/ctmrg/ctmrg.jl 90.41% <100.00%> (+0.13%) ⬆️
src/algorithms/ctmrg/initialization.jl 100.00% <100.00%> (ø)
src/environments/product_state_environments.jl 54.00% <54.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@leburgel leburgel marked this pull request as ready for review September 28, 2025 11:19
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
Comment thread src/algorithms/ctmrg/initialization.jl
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
lkdvos and others added 2 commits September 30, 2025 16:53
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
@Yue-Zhengyuan
Copy link
Copy Markdown
Member

I just noticed one more way to initialize the environment (I already have some code on this in my neighborhood tensor update branch), which we may call Neighbo(u)rhoodInitialization. This was mentioned in 1104.5463:

Initially, the corner and edge tensors at position [x,y] are constructed similarly as a reduced tensor a[x,y], by multiplying the tensor A[x,y] to its conjugate and fusing the bond indices,9 where we trace over the legs directed toward an open boundary.

For example, an edge tensor is constructed like this:

           2    
         ╱      
┌-----ket----- 4
|    ╱ |        
|   6  |   1    
|      | ╱      
└-----bra----- 3
     ╱          
    5           

In this way, the initialized environment directly have boundary dimension $\chi = D^2$.

Recently I realized that having a good initialization is also important during full update. Right now, I'm using the environment from the last iteration as initialization for the next step. But sometimes even this doesn't work well. So I kind of hope that we can finish this PR soon.

@lkdvos
Copy link
Copy Markdown
Member

lkdvos commented Nov 11, 2025

Would this give a different result from starting from environments that are the identity and doing a single step of ctmrg without truncating?

@Yue-Zhengyuan
Copy link
Copy Markdown
Member

Nice insight, they may indeed be the same thing... for fermions we may need to further ensure that the twists are correctly added.

@leburgel leburgel self-assigned this Nov 12, 2025
Comment thread src/algorithms/ctmrg/initialization.jl Outdated
@assert i in blocksectors(env.corners[dir, r, c])
for (c, b) in blocks(env.corners[dir, r, c])
b .= 0
c == i && (b[1, 1] = 1)
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 definitely need a test with fermionic iPEPS on this, in case parity-odd elements become -1 due to twists.

@pbrehmer pbrehmer mentioned this pull request Jan 21, 2026
@leburgel
Copy link
Copy Markdown
Member Author

Given the fact that this PR might be useful for #321, I'll try to pick this up again now. However, considering the original purpose, the review comments, and the new use case in #321, it's not entirely clear to me where to go with this. Let me try to summarize.

The original motivation for this PR was to solve #255, by making it 'easy' to initialize a CTMRG environment with a given bond dimension/virtual space by growing it from a smaller environment (with a product state being the default starting point. Basically, package up what people do all the time in a single method. The easiest way to do this would be to write a specialized initialize_ctmrg_environment.

However, since initializing environments is something very common, I tried to make it a bit more generic so that the same signature and initialization flavors could be reused in other places. This came out a bit awkward right away, as can be seen from the review comments. A first obvious problem is that the specification of virtual environment spaces really depends on what exactly we're doing, which gives rise to some awkward argument orderings. In addition, to actually 'grow' an environment we need to apply a few iterations of an algorithm (see ApplicationInitialization), which requires some algorithm settings to be specified. Again, this all made sense in the context of the original application to CTMRG, but looks very arbitrary when seen in a generic context.

Now in #321 there's an additional aspect, where we actually want to initialize a different kind of environment depending on the contraction algorithm we use. For now the C4v implementation uses the normal CTMRGEnv struct, but it would probably make more sense to use a custom C4vCTMRGEnv. Anticipating that we also want to support boundary MPS contractions soon™, this gives more different environment types for more contraction algorithms.

Trying to consider all of this feels a bit annoying, which is also why this PR got completely stalled in the first place. To get this moving, I think the first thing to decide is whether we want to solve the whole (potentially still growing) problem here, or we first just address the original issue #255.

To address the original problem, I would switch to just writing an initialize_ctmrg_environment with the minimal functionality required to address the issue.

To go for a full generic initialize_environment, I think it becomes inevitable to include an actual contraction algorithm instance in the arguments. Either this, or an equivalent named tuple that can identify multiple different contraction algorithms (and not just flavors of CTMRG like we support now). That would lead to something like

initialize_environment([T,] network, contraction_algorithm, initialization_style, virtual_space_specification)

for the generic case withing PEPSKit.jl alone. The question then becomes if this is compatible with other kinds of environment initializations (e.g. in MPSKit.jl), and if we still want it to be.

Asking for any and all opinions from @lkdvos, @pbrehmer and @Yue-Zhengyuan, after which I'll have a go at getting this to a point where it's usable.

return ProductStateEnv(f, T, Ds_north, Ds_east)
end
function ProductStateEnv(network::InfiniteSquareNetwork)
return ProductStateEnv(ones, scalartype(network), network) # TODO: do we want to use a different default function?
Copy link
Copy Markdown
Member

@Yue-Zhengyuan Yue-Zhengyuan Apr 11, 2026

Choose a reason for hiding this comment

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

I suggest we default to creating a "trivial" environment: with the trivial 1D chargeless environment spaces removed, the edge tensors should be an identity map. Currently it can be done with CTMRGEnv(SUWeight(peps)) for InfinitePEPS. But here your use of one fills all tensor elements, not only the diagonal elements.

We may consider adding a keyword argument to control whether we want to fill only the diagonal elements or all elements for the edge tensors.

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.

The problem is that this way of initializing only really makes sense for InfiniteSquareNetwork{<:PEPSSandwich}, while here I was trying to come up with something that works in general, in particular also for partition functions. To initialize a product state environment consisting of identities between two factors of the PEPS virtual space, we could call ProductStateEnv with a custom initializing function. Something like ProductStateEnv(bipartite_id, T, n), where bipartite_id is a custom function for initializing an identity between the two factors of a two-component ProductSpace.

So I fully agree with your suggestion, but it's not that straightforward to make this a default for all InfiniteSquareNetworks.

elt::Type{<:Number},
n::InfiniteSquareNetwork,
alg::RandomInitialization,
virtual_spaces... = oneunit(spacetype(n)),
Copy link
Copy Markdown
Member

@Yue-Zhengyuan Yue-Zhengyuan Apr 11, 2026

Choose a reason for hiding this comment

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

How about calling it environment_spaces (or env_spaces for short) to avoid confusion with the virtual spaces in n? (Unless you want to be consistent with src/environments/ctmrg_environments.jl)

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.

I was indeed trying to be consistent with src/environments/ctmrg_environments.jl, but I'm definitely open to renaming both instances it this would be less confusing.

Comment thread test/ctmrg/initialization.jl Outdated
@Yue-Zhengyuan
Copy link
Copy Markdown
Member

I applied ProductStateInitialization to finite-T SU tests.

Co-authored-by: Yue Zhengyuan <yuezy1997@icloud.com>
@leburgel
Copy link
Copy Markdown
Member Author

Kind of starting over on this one, hopefully I can work toward something useful that can be merged soon.

I'm giving up on trying to fit everything into a single initialize_environment method that works for all algorithms, and focusing on first writing a specific initialize_ctmrg_environment that solves the issue that actually motivated this PR in the first place.

Currently I have three initialization styles in mind that are useful:

  • RandomInitialization: initializes a random CTMRGEnv with gives virtual spaces, essentially coinciding with the current default constructor.
  • ProductStateInitialization: initializes a CTMRGEnv with trivial one-dimensional virtual spaces, corresponding to a product state environment to which we add trivial virtual legs.
  • ApplicationInitialization: initializes a CTMRGEnv by applying a single CTMRG iteration to a (optionally) given product state environment, giving an environment with a bond dimension $D^2$.

These should solve both #136 and #255 already, without considering how to use this in optimization for now. In particular, none of these take a contraction algorithm as an input, which means we can avoid the nightmare of plumbing in all possible configurations. Any additional steps needed for initialization should then just be handled by the user.

These last two initialization styles make use of a product state environment as an intermediate step, where especially for the ApplicationInitialization one might want to manually choose a specific product state as a boundary condition. Therefore, it seemed useful to me to introduce a dedicated ProductStateEnv to represent product state environments. In particular, I think we want this to work for general InfiniteSquareNetworks. This means I can't just repurpose BPEnv, which is just exactly a product state environment with some extra structure.

To push this over the line, I'm planning to

  • Replace BPEnv with a more general ProductStateEnv, and update all corresponding code.
  • Add additional initialization methods specifically for PEPS overlaps, in particular an initialization from a product state where the tensors are identities between the "ket" and "bra" PEPS virtual spaces.

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.

3 participants