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 MPOEnvironment
get_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).
See also this other thread
iDMRG sweep schedule asking a question in that direction.
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!