DensityMatrixMixer

Inheritance Diagram

Inheritance diagram of tenpy.algorithms.mps_common.DensityMatrixMixer

Methods

DensityMatrixMixer.__init__(options[, ...])

DensityMatrixMixer.mix_and_decompose_1site(...)

Decompose single-site wavefunction and expand/mix an adjacent bond.

DensityMatrixMixer.mix_and_decompose_2site(...)

Decompose two-site wavefunction and expand/mix enclosed bond(s).

DensityMatrixMixer.mix_rho(engine, theta, ...)

Calculate the (possibly mixed) reduced density matrices.

DensityMatrixMixer.mixed_svd_2site(engine, ...)

Mix and SVD-like decompose a two-site wavefunction.

DensityMatrixMixer.svd_from_rho(engine, ...)

Diagonalize rho_L, rho_R to rewrite theta as U S V with isometric U/V.

DensityMatrixMixer.update_amplitude(sweeps)

Update the amplitude, possibly disable the mixer.

Class Attributes and Properties

DensityMatrixMixer.can_decompose_1site

class tenpy.algorithms.mps_common.DensityMatrixMixer(options, sweep_activated=0)[source]

Bases: Mixer

Mixer based on reduced density matrices.

This mixer constructs density matrices as described in the original paper [white2005].

It implements mixed_svd_2site(), i.e. it replaces at the svd theta = U S VH with U-> A[i0] and VH -> B[i0+1]` being the new tensors in the MPS. It is thus best suited for two-site updates, e.g. two-site DMRG. Using it with one-site updates is possible, but introduces two-site costs and is inadvisable.

Given theta, one way to obtain U in the non-mixed case is to calculate and diagonalize the reduced density matrices rho_L = tr_R |theta><theta| = U S^2 U^H, and similarly diagonalize rho_R for VH. With the mixer, we perturb the rho_L (and/or rho_R) with terms from the relevant MPO – e.g. from the Hamiltonian in a DMRG groundstate search – before diagonalizing, see notes below.

See also

SubspaceExpansion

This mixer does mathematically the same, but circumvents the explicit contraction of the rho_L and rho_R.

Notes

The perturbation of rho_L is

\[rho_L = tr_R(|\theta><\theta|) \rightarrow tr_R(|\theta><\theta|) + a \sum_l h_l tr_R(|\theta><\theta|) h_l^\dagger\]

where a is the (small) perturbation amplitude and h_l are the left parts of the Hamiltonian going across the center bond (i0, i0+1). This perturbs eigenvalues of rho_L on the order of that amplitude. Note, however, that the eigenvalues of the perturbed rho_L are no longer related to the singular values of theta. Since we recover theta (at least up to truncation), the singular values are unchanged.

Pictorially, the left density matrix rho_L is given by:

|     mix_left=False           mix_left=True
|
|    .---theta---.            .---theta----.
|    |   |   |   |            |   |    \   |
|            |   |           LP---W0-.  \  |
|    |   |   |   |            |   |   \  | |
|    .---theta*--.                  mixL | |
|                             |   |   /  | |
|                            LP*--W0*-  /  |
|                             |   |    /   |
|                             .---theta*---.

Here, the mixL is a diagonal matrix with mostly the amplitude on the diagonal, except for the IdL and IdR indices of the MPO, where the entries are 1. and 0., respectively.

The right density matrix rho_R is mirrored accordingly.

mixed_svd_2site(engine: Sweep, theta: Array, i0: int, mix_left: bool, mix_right: bool, qtotal_LR=[None, None])[source]

Mix and SVD-like decompose a two-site wavefunction.

The goal is to split theta as follows:

|   -- theta --   ==>   -- U === S --- VH --
|      |   |               |           |

The LHS is equal to the RHS up to truncation and rescaling (we normalize to norm(S)==1). The double lines (===) indicate the mixed/expanded bond, here e.g. for mix_left=True, mix_right=False. U and VH are isometries like in an SVD, but S may be a general bond-matrix and in particular not necessarily diagonal or even square. Either one (or both) of the bonds next to S can be expanded / mixed. The isometry on a non-mixed side (e.g. U if mix_left=False) could have been obtained from an SVD of theta.

Parameters:
  • engine (Sweep) – The engine that is using this mixer.

  • theta (2D Array) – Two-site wavefunction prepared for SVD. Labels '(vL.p0)', '(p1.vR)'.

  • i0 (int) – The site index of the left site, i.e. such that theta lives on sites i0, i0 + 1.

  • mix_left (bool) – If the virtual index left of S should be expanded.

  • mix_right (bool) – If the virtual index right of S should be expanded.

  • qtotal_LR ([{charges}, {charges}] | None) – The desired qtotal for U and VH, respectively. If None, the qtotal are arbitrary.

Returns:

  • U (Array) – Left isometry as defined above. Labels '(vL.p)', 'vR'.

  • S (1D ndarray | 2D Array) – Singular values (1D ndarray) or general bond matrix (2D Array, labels 'vL', 'vR').

  • VH (Array) – Right isometry as defined above. Labels 'vL', '(p.vR)'.

  • err (TruncationError) – The truncation error introduced.

  • S_approx (ndarray) – Approximation of the singular values of theta. Exact if available.

mix_rho(engine: Sweep, theta: Array, i0: int, mix_left: bool, mix_right: bool)[source]

Calculate the (possibly mixed) reduced density matrices.

Parameters:
  • engine (Sweep) – The engine that is using this mixer.

  • theta (2D Array) – Two-site wavefunction prepared for SVD. Labels '(vL.p0)', '(p1.vR)'.

  • i0 (int) – The site index of the left site, i.e. such that theta lives on sites i0, i0 + 1.

  • mix_left (bool) – If the virtual index left of S should be expanded by perturbing rho_L.

  • mix_right (bool) – If the virtual index right of S should be expanded by perturbing rho_R.

Returns:

  • rho_L (Array) – Reduced density matrix on the left site or a perturbation thereof. Hermitian square array with labels '(vL.p0)', '(vL*.p0*)'.

  • rho_R (Array) – Reduced density matrix on the right site or a perturbation thereof. Hermitian square array with labels '(p1.vR)', '(p1*.vR*)'.

svd_from_rho(engine: Sweep, rho_L: Array, rho_R: Array, theta: Array, qtotal_LR)[source]

Diagonalize rho_L, rho_R to rewrite theta as U S V with isometric U/V.

If rho_L and rho_R were the actual density matrices of theta, this function just performs an SVD by diagonalizing rho_L with U and rho_R with VH and then rewriting theta == U (U^dagger theta VH^dagger VH) = U S V`. Since the actual rho_L and rho_R passed as arguments are perturbed by mix_rho, we get a similar decomposition but S is a general (non-diagonal) bond matrix.

Returns:

As defined in mixed_svd_2site().

Return type:

U, S, VH, err, S_approx

mix_and_decompose_1site(engine: Sweep, theta: Array, i0: int, move_right: bool)[source]

Decompose single-site wavefunction and expand/mix an adjacent bond.

For a right move, we decompose:

|   -- theta --   ==>   -- U === S === VH --
|        |                 |

For a left move:

|   -- theta --   ==>   -- U === S === VH --
|        |                             |

The LHS is equal to the RHS up to truncation and rescaling (we normalize to norm(S)==1). The double lines (===) indicate the mixed/expanded bonds. Only the tensor with a physical leg (e.g. U for a right move) is an isometry and is equivalent to the corresponding output of mixed_svd_2site(). It carries the qtotal of theta. The other (e.g. VH for a right move) is in general not isometric. S are the usual singular values.

The mixer can be injected in a sweeping algorithm by replacing the usual SVD of theta that shifts the canonical form with this method.

Parameters:
  • engine (Sweep) – The engine that is using this mixer.

  • theta (2D Array) – Single-site wavefunction prepared for SVD. Labels either '(vL.p0)', 'vR' for a right move, or 'vL', '(p0.vR)' for a left move.

  • i0 (int) – The site that theta lives on. The bond to be expanded is i0, i0 + 1 for a right move or i0 - 1, i0 for a left move.

  • move_right (bool | None) – Whether we move to the right (True), left (False), or dont move (None).

Returns:

  • U (Array) – Left part as defined above. Isometric for a right move. Labels '(vL.p)', 'vR' for a right move or 'vL', '(p.vR)' for a left move.

  • S (1D ndarray) – Singular values on the new bond.

  • VH (Array) – Right part as defined above. Isometric for a left move. Labels 'vL', '(p.vR)' for a right move or '(vL.p)', 'vR' for a left move.

  • err (TruncationError) – The truncation error introduced.

mix_and_decompose_2site(engine: Sweep, theta: Array, i0: int, mix_left: bool, mix_right: bool, qtotal_LR=None)[source]

Decompose two-site wavefunction and expand/mix enclosed bond(s).

This is a weaker version of mixed_svd_2site(). The decomposition is also:

|   -- theta --   ==>   -- U === S --- VH --
|      |   |               |           |

But only the tensors on mixed sites (e.g. only U for the case depicted above, i.e. mix_left=True, mix_right=False) are guaranteed to be isometric, while any non-mixed tensor (VH in this example) is in general not isometric. Other than that, parameters and returns are the same as for mixed_svd_2site().

The reason to relax the isometry condition is that the decomposition described above can be done using mix_and_decompose_1site() if mixed_svd_2site() is not implemented.

update_amplitude(sweeps)[source]

Update the amplitude, possibly disable the mixer.

Parameters:

sweeps (int) – The total number of performed sweeps, to check if we need to disable the mixer.

Returns:

mixer – Returns self if we should continue mixing, or None, if the mixer should be disabled.

Return type:

Mixer | None