# SubspaceExpansion

Inheritance Diagram

Methods

 `SubspaceExpansion.__init__`(options[, ...]) Decompose single-site wavefunction and expand/mix an adjacent bond. Decompose two-site wavefunction and expand/mix enclosed bond(s). `SubspaceExpansion.mixed_svd_2site`(engine, ...) Mix and SVD-like decompose a two-site wavefunction. Update the amplitude, possibly disable the mixer.

Class Attributes and Properties

 `SubspaceExpansion.can_decompose_1site`
class tenpy.algorithms.mps_common.SubspaceExpansion(options, sweep_activated=0)[source]

Bases: `Mixer`

Mixer of a direct subspace expansion.

Performs a subspace expansion following . It operates on single-site wave functions theta and is thus suitable for both single-site DMRG and two-site DMRG.

It is actually not necessary to fill the next_B with zeros as described in Hubig’s paper; rather we directly project the wR leg of VH onto the IdL index, which corresponds to taking the original theta (up to truncation).

Notes

Pictorially for a subspace expansion of the left U while moving right:

```|  --theta---            .-theta---                                  --U---S---VH---
|     |                  |   |                                         |       |
|             =dot=>    LP---H0--mix_L--     =SVD=>                    |       .---[IdL]
|                        |   |          (vL.p0),(wR.vR)
```

For a left-move:

```|  --theta---            --theta--.                         ---U---S---VH--
|     |                      |    |                            |       |
|            =dot=>  --mix_R-H0---RP         =SVD=>      [IdR]-.       |
|                            |    |     (vL.wL),(p0.vR)
```

Note that only the U during the right move (or VH during left-move) is guaranteed to be an isometry as expected in the canonical form; VH during the right-move contains a “subspace expansion” and does not fulfill the canonical `VH.dot(VH.conj().T) == eye`. Moreover, the U constructed from a two-site theta viewing the `'(p1.vR)` leg as just vR in the right-move is (mathematically) equivalent to the U returned by the `DensityMatrixMixer` (up to degenerate singular values).

In other words, the `mix_and_decompose_2site()` methods of `SubspaceExpansion` and `DensityMatrixMixer` should produce equivalent results; they only differ in the way they calculate U and V internally.

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.

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.

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