## How do environments grow in infinite DMRG?

General discussions on the ideas behind the algorithm.
Johannes
Posts: 442
Joined: 21 Jul 2018, 12:52
Location: TU Munich

### How do environments grow in infinite DMRG?

I got the following, very reasonable question via email:

In arXiv:1805.00055 there is a picture showing the update of the environment in the iDMRG (figure 11). I understood that between sweeps we are making two copies of the "central" system, and contracting it with the left and right environments. Then we are extending the range of sweeps, to incorporate those new sites. However, while reading the code I didn't find any function that was doing this insertion. The only methods that I found were update_LP and update_RP, which look exactly like the update one would do in the finite version of the algorithm. Is there some smart trick making these update_LP/RP methods equivalent to the insertion in the iDMRG? Maybe they are making use of some indices modulo L?
Johannes
Posts: 442
Joined: 21 Jul 2018, 12:52
Location: TU Munich

### Re: How do environments grow in infinite DMRG?

The figure 11 is a little bit misleading by stating that this happens between the sweeps, and it seems like we update both left and right environments at once. I chose to simplify in this figure to make it easier to grasp what is going on on the conceptual level - the figure makes clear that you need to absorb A tensors (= Lambda Gamma) into the left (one on each site), while absorbing B tensors (=Gamma Lambda) into the right one, if you want to keep everything translation invariant.

While this is conceptiually correct, it's not quite how it happens in the code. Indeed, the update_LP and update_RP functions, equivalent to / calling the corresponding MPOEnvironmentget_LP, are exactly the same as for the finite DMRG:
given the left environment on the left of site i, update_LP/get_LP contracts a column of the three tensors A W A.conj() from ket, MPO and bra into
the environment tensor, to get the left environment on the right of site i - exactly as shown in figure 8 d of the paper.

Looking back at Figure 11, you see that calling update_LP for i in range(0, L) grows the left environment by one MPS unit cell. This happens automatically during the right sweep, because we anyways need to update the left environments with the updated MPS tensors.

The trick why we enventually grow the environments indeed works because we take indices modulo L: in particular, the MPOEnvironment only saves at most L different left environments. So with the update_LP of the last site (L-1), you *overwrite* the environment that was previously on the left of site L.

In the following left sweep, you reload the left environments cached in the MPOEnvironment. On site n, you have an environment with n sites to the left saved - until you suddenly read site 0, where you have an environment containg already L sites. This is the point, where DMRG actually sees the increased environments.

To fully grasp what's going on, you also need to look at the (code of the) Sweep.get_sweep_schedule function, which defines how exactly the sweep is done, and which environments you update.

I think it also helps a lot to look at he "age" of the environments at each point. The "age" of an environment is the number of sites absorbed into it.
The system size that a two-site update of DMRG sees is the age of the left environment + 2 (for the two sites it's optimizing) + the age of the right environment of the effective H.
Insert the following print into the update_local function (after the first two lines):

Code: Select all

        print("ages of all left environments: ", self.env._LP_age)
print("ages of all right environments: ", self.env._RP_age)
print('DMRG update sites', i0, 'to', i0+n_opt - 1)
print('update age =', self.env.get_LP_age(i0),
'+', n_opt, '+', self.env.get_RP_age(i0 + n_opt - 1), '=', age)
print("update_LP_RP =", self.update_LP_RP)

The env._LP_age, env._RP_age are lists, indexed as "left of site 0, ..., L-1" for the left environments and "right of site 0, ... L-1" for the RP.
"None" in the lists of the environment ages indicates that there is no environment stored, as it is not needed in the future. This is an optimization we do to save RAM (since the environments are actually the biggest tensors in DMRG).

When you run this for a 10-site MPS, you get the following output for the first (right and left) sweep:

Code: Select all

ages of all left environments:  [0, None, None, None, None, None, None, None, None, None]
ages of all right environments:  [None, 8, 7, 6, 5, 4, 3, 2, 1, 0]
DMRG update sites 0 to 1
update age = 0 + 2 + 8 = 10
update_LP_RP = [True, True]
ages of all left environments:  [None, 1, None, None, None, None, None, None, None, None]
ages of all right environments:  [9, None, 7, 6, 5, 4, 3, 2, 1, 0]
DMRG update sites 1 to 2
update age = 1 + 2 + 7 = 10
update_LP_RP = [True, True]
ages of all left environments:  [None, None, 2, None, None, None, None, None, None, None]
ages of all right environments:  [9, 8, None, 6, 5, 4, 3, 2, 1, 0]
DMRG update sites 2 to 3
update age = 2 + 2 + 6 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, None, None, None, None, None, None]
ages of all right environments:  [9, 8, None, None, 5, 4, 3, 2, 1, 0]
DMRG update sites 3 to 4
update age = 3 + 2 + 5 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, None, None, None, None, None]
ages of all right environments:  [9, 8, None, None, None, 4, 3, 2, 1, 0]
DMRG update sites 4 to 5
update age = 4 + 2 + 4 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, 5, None, None, None, None]
ages of all right environments:  [9, 8, None, None, None, None, 3, 2, 1, 0]
DMRG update sites 5 to 6
update age = 5 + 2 + 3 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, 5, 6, None, None, None]
ages of all right environments:  [9, 8, None, None, None, None, None, 2, 1, 0]
DMRG update sites 6 to 7
update age = 6 + 2 + 2 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, 5, 6, 7, None, None]
ages of all right environments:  [9, 8, None, None, None, None, None, None, 1, 0]
DMRG update sites 7 to 8
update age = 7 + 2 + 1 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, 5, 6, 7, 8, None]
ages of all right environments:  [9, 8, None, None, None, None, None, None, None, 0]
DMRG update sites 8 to 9
update age = 8 + 2 + 0 = 10
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 2, 3, 4, 5, 6, 7, 8, 9]
ages of all right environments:  [9, 8, None, None, None, None, None, None, None, None]
DMRG update sites 9 to 10
update age = 9 + 2 + 9 = 20
update_LP_RP = [True, False]
ages of all left environments:  [10, None, 2, 3, 4, 5, 6, 7, 8, 9]
ages of all right environments:  [None, 8, None, None, None, None, None, None, None, None]
DMRG update sites 10 to 11
update age = 10 + 2 + 8 = 20
update_LP_RP = [True, True]
ages of all left environments:  [None, 11, 2, 3, 4, 5, 6, 7, 8, 9]
ages of all right environments:  [9, None, None, None, None, None, None, None, None, None]
DMRG update sites 9 to 10
update age = 9 + 2 + 9 = 20
update_LP_RP = [True, True]
ages of all left environments:  [10, 11, 2, 3, 4, 5, 6, 7, 8, None]
ages of all right environments:  [None, None, None, None, None, None, None, None, None, 10]
DMRG update sites 8 to 9
update age = 8 + 2 + 10 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, 3, 4, 5, 6, 7, None, None]
ages of all right environments:  [None, None, None, None, None, None, None, None, 11, 10]
DMRG update sites 7 to 8
update age = 7 + 2 + 11 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, 3, 4, 5, 6, None, None, None]
ages of all right environments:  [None, None, None, None, None, None, None, 12, 11, 10]
DMRG update sites 6 to 7
update age = 6 + 2 + 12 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, 3, 4, 5, None, None, None, None]
ages of all right environments:  [None, None, None, None, None, None, 13, 12, 11, 10]
DMRG update sites 5 to 6
update age = 5 + 2 + 13 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, 3, 4, None, None, None, None, None]
ages of all right environments:  [None, None, None, None, None, 14, 13, 12, 11, 10]
DMRG update sites 4 to 5
update age = 4 + 2 + 14 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, 3, None, None, None, None, None, None]
ages of all right environments:  [None, None, None, None, 15, 14, 13, 12, 11, 10]
DMRG update sites 3 to 4
update age = 3 + 2 + 15 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, 2, None, None, None, None, None, None, None]
ages of all right environments:  [None, None, None, 16, 15, 14, 13, 12, 11, 10]
DMRG update sites 2 to 3
update age = 2 + 2 + 16 = 20
update_LP_RP = [False, True]
ages of all left environments:  [10, 11, None, None, None, None, None, None, None, None]
ages of all right environments:  [None, None, 17, 16, 15, 14, 13, 12, 11, 10]
DMRG update sites 1 to 2
update age = 11 + 2 + 17 = 30
update_LP_RP = [False, True]


followed by the second sweep

Code: Select all

ages of all left environments:  [10, None, None, None, None, None, None, None, None, None]
ages of all right environments:  [None, 18, 17, 16, 15, 14, 13, 12, 11, 10]
DMRG update sites 0 to 1
update age = 10 + 2 + 18 = 30
update_LP_RP = [True, True]
ages of all left environments:  [None, 11, None, None, None, None, None, None, None, None]
ages of all right environments:  [19, None, 17, 16, 15, 14, 13, 12, 11, 10]
DMRG update sites 1 to 2
update age = 11 + 2 + 17 = 30
update_LP_RP = [True, True]
ages of all left environments:  [None, None, 12, None, None, None, None, None, None, None]
ages of all right environments:  [19, 18, None, 16, 15, 14, 13, 12, 11, 10]
DMRG update sites 2 to 3
update age = 12 + 2 + 16 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, None, None, None, None, None, None]
ages of all right environments:  [19, 18, None, None, 15, 14, 13, 12, 11, 10]
DMRG update sites 3 to 4
update age = 13 + 2 + 15 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, None, None, None, None, None]
ages of all right environments:  [19, 18, None, None, None, 14, 13, 12, 11, 10]
DMRG update sites 4 to 5
update age = 14 + 2 + 14 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, 15, None, None, None, None]
ages of all right environments:  [19, 18, None, None, None, None, 13, 12, 11, 10]
DMRG update sites 5 to 6
update age = 15 + 2 + 13 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, 15, 16, None, None, None]
ages of all right environments:  [19, 18, None, None, None, None, None, 12, 11, 10]
DMRG update sites 6 to 7
update age = 16 + 2 + 12 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, 15, 16, 17, None, None]
ages of all right environments:  [19, 18, None, None, None, None, None, None, 11, 10]
DMRG update sites 7 to 8
update age = 17 + 2 + 11 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, 15, 16, 17, 18, None]
ages of all right environments:  [19, 18, None, None, None, None, None, None, None, 10]
DMRG update sites 8 to 9
update age = 18 + 2 + 10 = 30
update_LP_RP = [True, False]
ages of all left environments:  [None, None, 12, 13, 14, 15, 16, 17, 18, 19]
ages of all right environments:  [19, 18, None, None, None, None, None, None, None, None]
DMRG update sites 9 to 10
update age = 19 + 2 + 19 = 40
update_LP_RP = [True, False]
ages of all left environments:  [20, None, 12, 13, 14, 15, 16, 17, 18, 19]
ages of all right environments:  [None, 18, None, None, None, None, None, None, None, None]
DMRG update sites 10 to 11
update age = 20 + 2 + 18 = 40
update_LP_RP = [True, True]
ages of all left environments:  [None, 21, 12, 13, 14, 15, 16, 17, 18, 19]
ages of all right environments:  [19, None, None, None, None, None, None, None, None, None]
DMRG update sites 9 to 10
update age = 19 + 2 + 19 = 40
update_LP_RP = [True, True]
ages of all left environments:  [20, 21, 12, 13, 14, 15, 16, 17, 18, None]
ages of all right environments:  [None, None, None, None, None, None, None, None, None, 20]
DMRG update sites 8 to 9
update age = 18 + 2 + 20 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, 13, 14, 15, 16, 17, None, None]
ages of all right environments:  [None, None, None, None, None, None, None, None, 21, 20]
DMRG update sites 7 to 8
update age = 17 + 2 + 21 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, 13, 14, 15, 16, None, None, None]
ages of all right environments:  [None, None, None, None, None, None, None, 22, 21, 20]
DMRG update sites 6 to 7
update age = 16 + 2 + 22 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, 13, 14, 15, None, None, None, None]
ages of all right environments:  [None, None, None, None, None, None, 23, 22, 21, 20]
DMRG update sites 5 to 6
update age = 15 + 2 + 23 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, 13, 14, None, None, None, None, None]
ages of all right environments:  [None, None, None, None, None, 24, 23, 22, 21, 20]
DMRG update sites 4 to 5
update age = 14 + 2 + 24 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, 13, None, None, None, None, None, None]
ages of all right environments:  [None, None, None, None, 25, 24, 23, 22, 21, 20]
DMRG update sites 3 to 4
update age = 13 + 2 + 25 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, 12, None, None, None, None, None, None, None]
ages of all right environments:  [None, None, None, 26, 25, 24, 23, 22, 21, 20]
DMRG update sites 2 to 3
update age = 12 + 2 + 26 = 40
update_LP_RP = [False, True]
ages of all left environments:  [20, 21, None, None, None, None, None, None, None, None]
ages of all right environments:  [None, None, 27, 26, 25, 24, 23, 22, 21, 20]
DMRG update sites 1 to 2
update age = 21 + 2 + 27 = 50
update_LP_RP = [False, True]

ending up with

Code: Select all

ages of all left environments:  [20, None, None, None, None, None, None, None, None, None]
ages of all right environments:  [None, 28, 27, 26, 25, 24, 23, 22, 21, 20]

As you can see, you indeed have grown the left and right environments by each 10 sites during each sweep.
The update itself sees the constant age until it jumps by 10 when you reach an environment from a previous sweep where you already absorbed 10 more sites, once when updating sites 9 to 10 in the right move, and updating sites 1 to 2 in the left move.

I hope this example makes everything clear!
Ozaru9000
Posts: 9
Joined: 01 Nov 2019, 18:29

### Re: How do environments grow in infinite DMRG?

Great explanation! One last question - is the canonical form preserved by making use of the Vidal notation? That is, while getting two-site "theta" tensor on sites L-1 and 0 we simply incorporate SL singular values into the (L-1)th tensor and SR into 0th tensor?