Skip to content

Commit

Permalink
BlockTensorMap (#199)
Browse files Browse the repository at this point in the history
This is an admittedly too large PR that involves changing the MPO tensors and associated environments to start using `BlockTensorKit`. This allows a large amount of code logic to be offloaded and separated out, which leads to overall better readability, and should improve maintenance and development of this package in the future.

---

* Update for TensorKit changes

* Add FiniteMPOHamiltonian

* Add linearalgebra

* Rewrite Operators

* Add virtualspace functions QP

* Add `axes` multiline

* Add PeriodicVector and PeriodicMatrix constructors

* update tests

* Start refactor environments

* update SVDCut

* Update excitations

* Update TimeEvolution MPO

* Update ED

* update derivatives and transfers

* Add utility functions

* Update convenience functions

* fix very important typo

* compat with TensorKitManifolds

* remove @shows

* change opp to operator, like it is in `MultipleEnvironments`

* add copy methods for `FiniteMPOHamiltonian` and `InfiniteMPOHamiltonian`

* add creation of `FiniteMPOHamiltonian` and `InfiniteMPOHamiltonian` directly from a local operator

* change MPOHamiltonian copies to deepcopies

* implement scalar multiplication for `FiniteMPOHamiltonian` and `InfiniteMPOHamiltonian`

* split MPOHamiltonian creation from local operator into Finite and Infinite case

* fix typo in fidelity susceptibility testset

* change WI() to WI

* check for (and don't add) zero-valued A-blocks in `AbstractMPOHamiltonian` addition

* formatting

* remove creation of `FiniteMPOHamiltonian` from local operator

* update BlockTensorKit compat

* Add WindowMPS environments

* Add convenience methods quasiparticles

* Fix small typo

* Add length to quasiparticle state tests

* Relax MPO setindex

* fix some wrong references to fields

* Small style change in linalg

* Update some mpo linalg

* change tensortype inference in `*(::InfiniteMPOHamiltonian, ::InfiniteMPOHamiltonian)`

* convenience methods

* Fix some operator tests

* update DenseMPO

* Fix type signature

* add `open_boundary_conditions` and extend all boundary condition methods to `InfiniteMPOHamiltonian`s

* Add more physicalspace methods

* readd `propagator` methods and change function signatures to new types

* Add conj

* implementing fix from `*(::Inf.Ham.,::Inf.Ham)` in the finite case

* some more test/operators fixes

* add `randomize!(::AbstractBlockTensorMap)`

* Add *(::InfiniteMPO, ::InfiniteMPS)

* use methods instead of removed MPO properties

* add creation of `InfiniteMPO` from `AbstractTensorMaps`

* fix creation of `DenseMPO`

* fix periodic boundary conditions test

* physicalspace never returns SumSpace

* Fix `*(::InfiniteMPO, ::InfiniteMPS)`

* More operator test fixes

* Some more linalg cleanup

* some more operators test cleanup

* change dynamical DMRG test case

* Fix DynamicalDMRG

* add `show()` for `AbstractMPO`s

* Add / for multiplied operator

* small fix

* Add dropzeros in H*H

* add `BlockTensorKit.show_braille(::AbstractHMPO)`

* important copy fix

* little bit cleanup

* More generic linalg

* Clean up MPO structs

* Fix infiniteMPOEnvironments

* Fix expval for mpo

* fix overlylong excitations test

* fidelity_susceptibility fix

* Changes to accomodate new `MPOHamiltonian` type

* Extend `BlockTensorKit.show_braille()` to SparseMPOs

* drop zeros after imposing PBC

* change `make_time_mpo` to be compatible with `FiniteMPOHamiltonian`s

* implement `remove_orphans` for `FiniteMPO`s

* add conversion to `DenseMPO` from `MPOHamiltonian`s

* remove redundant check in `remove_orphans!(::FiniteMPO)`

* fix multiplication of `FiniteMPOHamiltonian`s

* move boundary condition application step

* use `droptol!()`

* use `droptol!()`

* rename `BlockTensorKit.braille(::SparseMPO)` to `braille(::SparseMPO)` for convenience

* add assert for MPOs that aren't the same size everywhere

* use finite Hamiltonian for finite mps test

* add L parameter to approximate tests

* fix converting Hamiltonian to 'square' one

* change only() to TensorMap()

* compensate for env fieldname changes

* compensate for env namechange

* change approximate test

* remove return statement for aesthetics and consistency

* use dot notation for dropzeros in periodic_boundary_conditions

* change boundary condition application in pbc

* delete old environment stuct and code

* rename permpoinfenv to infinitempoenv

* add `FiniteMPO` to finite environments arguments

* change `permpoinfenv` to `InfiniteMPOEnvironments` in docs

* oneline `dropzeros` step in `periodic_boundary_conditions`

* implement new test for `periodic_boundary_conditions` and comment out the old one

* formatting change

* Version changes

* robust `storagetype` handling

* implement pr 180 '3 site tests' into blocktensor2 branch

* format

* cleanup and fix `force_planar`

* Fix arguments being reversed

* Fix periodic boundary

* formatter

* Fix deprecation warning in test

* Improve implementation of multiplying MPOs

* Fix for InfiniteMPOHamiltonian

* Remove `RecursiveVec`

* Update outdated names

* improve MPOHamiltonian constructors

* Add `add_physical_charge`

* fixes MPO constructor

* Fix mpohamiltonian constructor

* Fix `make_time_mpo` extensions step

* TaylorCluster optimizations

* Update gitignore

* change test tol

* update oplus syntax

* Bump julia version in tests

* Rename environments/files and cleanup unused code

* remove more unused code

* remove more unused code

* small fix in examples

* Add Aqua and fix some tests

* more unused code deletion

* more unused code deletion

* small formatting change

* revert Aqua-related change

* Restrict Aqua tests for now

* more unused code removal

* more unused code removal

* improve test stability

* minor doc updates

* Temporary fix for docs

---------

Co-authored-by: Victor <[email protected]>
  • Loading branch information
lkdvos and VictorVanthilt authored Dec 12, 2024
1 parent cd81eef commit 19fae27
Show file tree
Hide file tree
Showing 65 changed files with 3,185 additions and 5,578 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.8' # minimal supported version
- 'lts' # minimal supported version
- '1' # latest released Julia version
group:
- states
Expand Down
30 changes: 21 additions & 9 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name = "MPSKit"
uuid = "bb1c41ca-d63c-52ed-829e-0820dda26502"
authors = ["Maarten Van Damme", "Jutho Haegeman", "Lukas Devos", "Gertian Roose", "Markus Hauru", "Daan Maertens"]
version = "0.11.6"
authors = "Lukas Devos, Maarten Van Damme and contributors"
version = "0.12.0"

[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd"
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
FastClosures = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a"
FoldsThreads = "9c68100b-dfe1-47cf-94c8-95104e173443"
Expand All @@ -14,37 +15,48 @@ LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
OptimKit = "77e91f04-9b3b-57a6-a776-40b61faaebe0"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec"
TensorKitManifolds = "11fa318c-39cb-4a83-b1ed-cdc7ba1e3684"
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
Transducers = "28d57a85-8fef-5791-bfe6-a80928e7c999"
TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"

[compat]
Accessors = "0.1"
Aqua = "0.8.9"
BlockTensorKit = "0.1.1"
FLoops = "0.1, 0.2"
FastClosures = "0.3"
FoldsThreads = "0.1"
KrylovKit = "0.8.3"
LinearAlgebra = "1.6"
LoggingExtras = "1"
LoggingExtras = "~1.0"
OptimKit = "0.3.1"
Pkg = "1"
Plots = "1.40"
Preferences = "1"
Printf = "1"
Random = "1"
RecipesBase = "1.1"
TensorKit = "0.12"
TensorKitManifolds = "0.5, 0.6, 0.7"
TensorOperations = "4"
TensorKit = "0.13"
TensorKitManifolds = "0.7"
TensorOperations = "5"
Test = "1"
TestExtras = "0.3"
Transducers = "0.4"
TupleTools = "1.6.0"
VectorInterface = "0.2, 0.3, 0.4, 0.5"
julia = "1.8"
julia = "1.10"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a"

[targets]
test = ["Pkg", "Test", "TestExtras", "Plots"]
test = ["Aqua", "Pkg", "Test", "TestExtras", "Plots"]
1 change: 0 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502"
MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
Expand Down
26 changes: 17 additions & 9 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ operators and models.
using TensorOperations
using TensorKit
using MPSKit
using MPSKitModels
using LinearAlgebra: norm
```

Expand All @@ -48,7 +47,6 @@ using LinearAlgebra
using TensorOperations
using TensorKit
using MPSKit
using MPSKitModels
```

Finite MPS are characterised by a set of tensors, one for each site, which each have 3 legs.
Expand Down Expand Up @@ -106,10 +104,16 @@ Using the pre-defined models in `MPSKitModels`, we can construct the groundstate
transverse field Ising model:

```@example finitemps
H = transverse_field_ising(; J=1.0, g=0.5)
J = 1.0
g = 0.5
lattice = fill(ComplexSpace(2), 10)
X = TensorMap(ComplexF64[0 1; 1 0], ComplexSpace(2), ComplexSpace(2))
Z = TensorMap(ComplexF64[1 0; 0 -1], space(X))
H = FiniteMPOHamiltonian(lattice, (i, i+1) => -J * X ⊗ X for i in 1:length(lattice)-1) +
FiniteMPOHamiltonian(lattice, (i,) => - g * Z for i in 1:length(lattice))
find_groundstate!(mps, H, DMRG(; maxiter=10))
E0 = expectation_value(mps, H)
println("<mps|H|mps> = $(sum(real(E0)) / length(mps))")
println("<mps|H|mps> = $real(E0)")
```

### Infinite Matrix Product States
Expand All @@ -119,7 +123,6 @@ using LinearAlgebra
using TensorOperations
using TensorKit
using MPSKit
using MPSKitModels
```

Similarly, an infinite MPS can be constructed by specifying the tensors for the unit cell,
Expand Down Expand Up @@ -173,11 +176,16 @@ println("<mps|𝕀₁|mps> = $N2")
observable computed from the MPS would either blow up to infinity or vanish to zero.

Finally, the MPS can be optimized in order to determine groundstates of given Hamiltonians.
Using the pre-defined models in `MPSKitModels`, we can construct the groundstate for the
transverse field Ising model:
There are plenty of pre-defined models in `MPSKitModels`, but we can also manually construct
the groundstate for the transverse field Ising model:

```@example infinitemps
H = transverse_field_ising(; J=1.0, g=0.5)
J = 1.0
g = 0.5
lattice = PeriodicVector([ComplexSpace(2)])
X = TensorMap(ComplexF64[0 1; 1 0], ComplexSpace(2), ComplexSpace(2))
Z = TensorMap(ComplexF64[1 0; 0 -1], space(X))
H = InfiniteMPOHamiltonian(lattice, (1, 2) => -J * X ⊗ X, (1,) => - g * Z)
mps, = find_groundstate(mps, H, VUMPS(; maxiter=10))
E0 = expectation_value(mps, H)
println("<mps|H|mps> = $(sum(real(E0)) / length(mps))")
Expand Down Expand Up @@ -212,4 +220,4 @@ request or an issue on the [GitHub repository](https://github.com/QuantumKitHub/
- Gertian Roose, Laurens Vanderstraeten, Jutho Haegeman, and Nick Bultinck. Anomalous domain wall condensation in a modified ising chain. Phys. Rev. B, 99: 195132, May 2019. 10.1103/​PhysRevB.99.195132.
https:/​/​doi.org/​10.1103/​PhysRevB.99.195132
- Roose, G., Bultinck, N., Vanderstraeten, L. et al. Lattice regularisation and entanglement structure of the Gross-Neveu model. J. High Energ. Phys. 2021, 207 (2021). https://doi.org/10.1007/JHEP07(2021)207
- Roose, G., Haegeman, J., Van Acoleyen, K. et al. The chiral Gross-Neveu model on the lattice via a Landau-forbidden phase transition. J. High Energ. Phys. 2022, 19 (2022). https://doi.org/10.1007/JHEP06(2022)019
- Roose, G., Haegeman, J., Van Acoleyen, K. et al. The chiral Gross-Neveu model on the lattice via a Landau-forbidden phase transition. J. High Energ. Phys. 2022, 19 (2022). https://doi.org/10.1007/JHEP06(2022)019
33 changes: 8 additions & 25 deletions docs/src/lib/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,19 @@ MPSMultiline

## Operators
```@docs
FiniteMPO
SparseMPO
DenseMPO
AbstractMPO
MPO
MPOHamiltonian
```

## Environments
```@docs
MPSKit.AbstractInfEnv
MPSKit.PerMPOInfEnv
MPSKit.MPOHamInfEnv
MPSKit.FinEnv
MPSKit.IDMRGEnvs
```

## Generic actions
```@docs
∂C
∂∂C
∂AC
∂∂AC
∂AC2
∂∂AC2
c_proj
ac_proj
ac2_proj
transfer_left
transfer_right
MPSKit.AbstractMPSEnvironments
MPSKit.AbstractInfiniteEnvironments
MPSKit.InfiniteMPOEnvironments
MPSKit.InfiniteMPOHamiltonianEnvironments
MPSKit.FiniteEnvironments
MPSKit.IDMRGEnvironments
```

## Algorithms
Expand Down
24 changes: 16 additions & 8 deletions docs/src/man/algorithms.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
```@meta
DocTestSetup = quote
using MPSKit, MPSKitModels, TensorKit
end
DocTestSetup = :( using MPSKit, TensorKit)
```

# [Algorithms](@id um_algorithms)
Expand Down Expand Up @@ -168,7 +166,9 @@ in the transverse field Ising model, we calculate the first excited state as sho
provided code snippet, amd check the accuracy against theoretical values. Some deviations
are expected, both due to finite-bond-dimension and finite-size effects.

```jldoctest; output = false
<!-- TODO: reenable doctest -->

```julia
# Model parameters
g = 10.0
L = 16
Expand All @@ -194,7 +194,9 @@ in the unit cell in a plane-wave superposition, requiring momentum specification
[Haldane gap](https://iopscience.iop.org/article/10.1088/0953-8984/1/19/001) computation in
the Heisenberg model illustrates this approach.

```jldoctest; output = false
<!-- TODO: reenable doctest -->

```julia
# Setting up the model and momentum
momentum = π
H = heisenberg_XXX()
Expand All @@ -219,7 +221,9 @@ trivial total charge. However, quasiparticles with different charges can be obta
the sector keyword. For instance, in the transverse field Ising model, we consider an
excitation built up of flipping a single spin, aligning with `Z2Irrep(1)`.

```jldoctest; output = false
<!-- TODO: reenable doctest -->

```julia
g = 10.0
L = 16
H = transverse_field_ising(Z2Irrep; g)
Expand Down Expand Up @@ -260,7 +264,9 @@ often referred to as the 'Chepiga ansatz', named after one of the authors of thi

This is supported via the following syntax:

```jldoctest
<!-- TODO: reenable doctest -->

```julia
g = 1.0
L = 16
H = transverse_field_ising(; g)
Expand All @@ -278,7 +284,9 @@ true
In order to improve the accuracy, a two-site version also exists, which varies two
neighbouring sites:

```jldoctest
<!-- TODO: reenable doctest -->

```julia
g = 1.0
L = 16
H = transverse_field_ising(; g)
Expand Down
59 changes: 15 additions & 44 deletions docs/src/man/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ O_xzx_sum * FiniteMPS(3, ℂ^2, ℂ^4)
make sure that the virtual spaces do not increase past the maximal virtual space that
is dictated by the requirement of being full-rank tensors.

## MPOHamiltonian
## FiniteMPOHamiltonian

We can also represent quantum Hamiltonians in the same form. This is done by converting a
sum of local operators into a single MPO operator. The resulting operator has a very
specific structure, and is often referred to as a *Jordan block MPO*.

This object can be constructed as an MPO by using the [`MPOHamiltonian`](@ref) constructor,
This object can be constructed as an MPO by using the [`FiniteMPOHamiltonian`](@ref) constructor,
which takes two crucial pieces of information:

1. An array of `VectorSpace` objects, which determines the local Hilbert spaces of the
Expand All @@ -103,16 +103,16 @@ h = 0.5
chain = fill(ℂ^2, 3) # a finite chain of 4 sites, each with a 2-dimensional Hilbert space
single_site_operators = [1 => -h * S_z, 2 => -h * S_z, 3 => -h * S_z]
two_site_operators = [(1, 2) => -J * S_x ⊗ S_x, (2, 3) => -J * S_x ⊗ S_x]
H_ising = MPOHamiltonian(chain, single_site_operators..., two_site_operators...);
H_ising = FiniteMPOHamiltonian(chain, single_site_operators..., two_site_operators...);
```

Various alternative constructions are possible, such as using a `Dict` with key-value pairs
that specify the operators, or using generator expressions to simplify the construction.

```@example operators
H_ising′ = -J * MPOHamiltonian(chain,
H_ising′ = -J * FiniteMPOHamiltonian(chain,
(i, i + 1) => S_x ⊗ S_x for i in 1:(length(chain) - 1)) -
h * MPOHamiltonian(chain, i => S_z for i in 1:length(chain))
h * FiniteMPOHamiltonian(chain, i => S_z for i in 1:length(chain))
isapprox(H_ising, H_ising′; atol=1e-6)
```

Expand Down Expand Up @@ -147,9 +147,9 @@ for I in eachindex(IndexCartesian(), square)
end
end
H_ising_2d = MPOHamiltonian(square, local_operators) +
MPOHamiltonian(square, horizontal_operators) +
MPOHamiltonian(square, vertical_operators);
H_ising_2d = FiniteMPOHamiltonian(square, local_operators) +
FiniteMPOHamiltonian(square, horizontal_operators) +
FiniteMPOHamiltonian(square, vertical_operators);
```

There are various utility functions available for constructing more advanced lattices, for
Expand Down Expand Up @@ -224,20 +224,22 @@ Vᵣ = [0, 0, 1]
expand(Vₗ * prod(Ws) * Vᵣ)
```

The `MPOHamiltonian` constructor can also be used to construct the operator from this most
The `FiniteMPOHamiltonian` constructor can also be used to construct the operator from this most
general form, by supplying a 3-dimensional array $W$ to the constructor. Here, the first
dimension specifies the site in the unit cell, the second dimension specifies the row of the
matrix, and the third dimension specifies the column of the matrix.

```@example operators
<!-- TODO: reenable doctest -->

```julia
data = Array{Any,3}(missing, 1, 3, 3) # missing is interpreted as zero
data[1, 1, 1] = id(Matrix{ComplexF64}, ℂ^2)
data[1, 1, 1] = id(ComplexF64, ℂ^2)
data[1, 3, 3] = 1 # regular numbers are interpreted as identity operators
data[1, 1, 2] = -J * S_x
data[1, 2, 3] = S_x
data[1, 1, 3] = -h * S_z
data_range = repeat(data, 4, 1, 1) # make 4 sites long
H_ising″ = MPOHamiltonian(data_range)
H_ising″ = FiniteMPOHamiltonian(data_range)
```

MPSKit will then automatically attach the correct boundary vectors to the Hamiltonian whenever this is required.
Expand All @@ -255,42 +257,11 @@ MPSKit will then automatically attach the correct boundary vectors to the Hamilt
!!! warning
This part is still a work in progress

Because of the discussion above, the `MPOHamiltonian` object is in fact just a `FiniteMPO`,
Because of the discussion above, the `FiniteMPOHamiltonian` object is in fact just an `AbstractMPO`,
with some additional structure. This means that similar operations and properties are
available, such as the virtual spaces, or the individual tensors. However, the block
structure of the operator means that now the virtual spaces are not just a single space, but
a collection (direct sum) of spaces, one for each row/column.

<!-- TODO: add examples virtualspace once blocktensors are in place -->

## DenseMPO

This operator is used for statistical physics problems. It is simply a periodic array of mpo tensors.

Can be created using
```julia
DenseMPO(t::AbstractArray{T,1}) where T<:MPOTensor
```

## SparseMPO

`SparseMPO` is similar to a `DenseMPO`, in that it again represents an mpo tensor, periodically repeated. However this type keeps track of all internal zero blocks, allowing for a more efficient representation of certain operators (such as time evolution operators and quantum hamiltonians). You can convert a sparse mpo to a densempo, but the converse does not hold.


Indexing a `SparseMPO` returns a `SparseMPOSlice` object, which has 3 fields

```@docs
MPSKit.SparseMPOSlice
```

When indexing a `SparseMPOSlice` at index `[j, k]` (or equivalently `SparseMPO[i][j, k]`), the code looks up the corresponding field in `Os[j, k]`. Either that element is a tensormap, in which case it gets returned. If it equals `zero(E)`, then we return a tensormap
```julia
domspaces[j] * pspace pspace * imspaces[k]
```
with norm zero. If the element is a nonzero number, then implicitly we have the identity operator there (multiplied by that element).

The idea here is that you don't have to worry about the underlying structure, you can just index into a sparsempo as if it is a vector of matrices. Behind the scenes we then optimize certain contractions by using the sparsity structure.

SparseMPO are always assumed to be periodic in the first index (position).
In this way, we can both represent periodic infinite mpos and place dependent finite mpos.

Loading

0 comments on commit 19fae27

Please sign in to comment.