Skip to content

Commit 046f4d0

Browse files
committed
Couple more fixes and a CUDA+MPS example
1 parent 4913563 commit 046f4d0

11 files changed

Lines changed: 208 additions & 37 deletions

File tree

Project.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ TensorKitManifolds = "11fa318c-39cb-4a83-b1ed-cdc7ba1e3684"
2323
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
2424
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"
2525

26+
[weakdeps]
27+
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
28+
29+
[extensions]
30+
MPSKitAdaptExt = "Adapt"
31+
2632
[compat]
2733
Accessors = "0.1"
34+
Adapt = "4"
2835
Aqua = "0.8.9"
2936
BlockTensorKit = "0.3.4"
3037
Combinatorics = "1"
@@ -51,6 +58,7 @@ VectorInterface = "0.2, 0.3, 0.4, 0.5"
5158
julia = "1.10"
5259

5360
[extras]
61+
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
5462
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
5563
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
5664
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
@@ -59,4 +67,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
5967
TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a"
6068

6169
[targets]
62-
test = ["Aqua", "Pkg", "Test", "TestExtras", "Plots", "Combinatorics"]
70+
test = ["Adapt", "Aqua", "Pkg", "Test", "TestExtras", "Plots", "Combinatorics"]
71+
72+
[sources]
73+
TensorKit = {url="https://github.com/QuantumKitHub/TensorKit.jl/", rev="ksh/cuda_tweaks"}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using Markdown
2+
3+
md"""
4+
# [The Hard Hexagon model](@id demo_hardhexagon)
5+
6+
![logo](hexagon.svg)
7+
8+
Tensor networks are a natural way to do statistical mechanics on a lattice.
9+
As an example of this we will extract the central charge of the hard hexagon model.
10+
This model is known to have central charge 0.8, and has very peculiar non-local (anyonic) symmetries.
11+
Because TensorKit supports anyonic symmetries, so does MPSKit.
12+
To follow the tutorial you need the following packages.
13+
"""
14+
15+
using MatrixAlgebraKit, MPSKit, MPSKitModels, TensorKit, Plots, Polynomials, Adapt, CUDA, cuTENSOR
16+
17+
MPSKit.Defaults.alg_qr() = CUSOLVER_HouseholderQR(; positive = true)
18+
MPSKit.Defaults.alg_svd() = CUSOLVER_QRIteration()
19+
MPSKit.Defaults.alg_lq() = LQViaTransposedQR(CUSOLVER_HouseholderQR(; positive = true))
20+
21+
#src # for reproducibility:
22+
#src using Random
23+
#src Random.seed!(123)
24+
25+
md"""
26+
The [hard hexagon model](https://en.wikipedia.org/wiki/Hard_hexagon_model) is a 2-dimensional lattice model of a gas, where particles are allowed to be on the vertices of a triangular lattice, but no two particles may be adjacent.
27+
This can be encoded in a transfer matrix with a local MPO tensor using anyonic symmetries, and the resulting MPO has been implemented in MPSKitModels.
28+
29+
In order to use these anyonic symmetries, we need to generalise the notion of the bond dimension and define how it interacts with the symmetry. Thus, we implement away of converting integers to symmetric spaces of the given dimension, which provides a crude guess for how the final MPS would distribute its Schmidt spectrum.
30+
"""
31+
mpo = adapt(CuArray, hard_hexagon())
32+
P = physicalspace(mpo, 1)
33+
function virtual_space(D::Integer)
34+
_D = round(Int, D / sum(dim, values(FibonacciAnyon)))
35+
return Vect[FibonacciAnyon](sector => _D for sector in (:I, ))
36+
end
37+
38+
@assert isapprox(dim(virtual_space(100)), 100; atol = 3)
39+
40+
md"""
41+
## The leading boundary
42+
43+
One way to study statistical mechanics in infinite systems with tensor networks is by approximating the dominant eigenvector of the transfer matrix by an MPS.
44+
This dominant eigenvector contains a lot of hidden information.
45+
For example, the free energy can be extracted by computing the expectation value of the mpo.
46+
Additionally, we can compute the entanglement entropy as well as the correlation length of the state:
47+
"""
48+
49+
D = 10
50+
V = virtual_space(D)
51+
ψ₀ = InfiniteMPS(CuVector{ComplexF64, CUDA.DeviceMemory}, [P], [V])
52+
ψ, envs, = leading_boundary(
53+
ψ₀, mpo,
54+
VUMPS(; verbosity = 0, alg_eigsolve = MPSKit.Defaults.alg_eigsolve(; ishermitian = false))
55+
) # use non-hermitian eigensolver
56+
F = real(expectation_value(ψ, mpo))
57+
S = real(first(entropy(ψ)))
58+
ξ = correlation_length(ψ)
59+
println("F = $F\tS = $S\tξ = ")
60+
61+
md"""
62+
## The scaling hypothesis
63+
64+
The dominant eigenvector is of course only an approximation. The finite bond dimension enforces a finite correlation length, which effectively introduces a length scale in the system. This can be exploited to formulate a scaling hypothesis [pollmann2009](@cite), which in turn allows to extract the central charge.
65+
66+
First we need to know the entropy and correlation length at a bunch of different bond dimensions. Our approach will be to re-use the previous approximated dominant eigenvector, and then expanding its bond dimension and re-running VUMPS.
67+
According to the scaling hypothesis we should have ``S \propto \frac{c}{6} log(ξ)``. Therefore we should find ``c`` using
68+
"""
69+
70+
function scaling_simulations(
71+
ψ₀, mpo, Ds; verbosity = 0, tol = 1.0e-6,
72+
alg_eigsolve = MPSKit.Defaults.alg_eigsolve(; ishermitian = false)
73+
)
74+
entropies = similar(Ds, Float64)
75+
correlations = similar(Ds, Float64)
76+
alg = VUMPS(; verbosity, tol, alg_eigsolve)
77+
78+
ψ, envs, = leading_boundary(ψ₀, mpo, alg)
79+
entropies[1] = real(entropy(ψ)[1])
80+
correlations[1] = correlation_length(ψ)
81+
82+
for (i, d) in enumerate(diff(Ds))
83+
ψ, envs = changebonds(ψ, mpo, OptimalExpand(; trscheme = truncrank(d)), envs)
84+
ψ, envs, = leading_boundary(ψ, mpo, alg, envs)
85+
entropies[i + 1] = real(entropy(ψ)[1])
86+
correlations[i + 1] = correlation_length(ψ)
87+
end
88+
return entropies, correlations
89+
end
90+
91+
bond_dimensions = 10:5:25
92+
ψ₀ = InfiniteMPS(CuVector{ComplexF64}, [P], [virtual_space(bond_dimensions[1])])
93+
Ss, ξs = scaling_simulations(ψ₀, mpo, bond_dimensions)
94+
95+
f = fit(log.(ξs), 6 * Ss, 1)
96+
c = f.coeffs[2]
97+
98+
#+
99+
100+
p = plot(; xlabel = "logarithmic correlation length", ylabel = "entanglement entropy")
101+
p = plot(log.(ξs), Ss; seriestype = :scatter, label = nothing)
102+
plot!(p, ξ -> f(ξ) / 6; label = "fit")

ext/MPSKitAdaptExt.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module MPSKitAdaptExt
2+
3+
using MPSKit, Adapt
4+
5+
function Adapt.adapt_structure(to, x::MPSKit.MPO{TO}) where {TO}
6+
terms′ = map(o->adapt(to, o), x.O)
7+
return MPSKit.MPO(terms′)
8+
end
9+
10+
function Adapt.adapt_structure(to, x::MPSKit.MPOHamiltonian{TO}) where {TO}
11+
terms′ = map(w->adapt(to, w), x.W)
12+
return MPSKit.MPOHamiltonian(terms′)
13+
end
14+
15+
end

src/algorithms/expval.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ function expectation_value(
192192
ψ::FiniteMPS, O::ProjectionOperator,
193193
envs::FiniteEnvironments = environments(ψ, O)
194194
)
195-
ens = zeros(storagetype(ψ), length(ψ))
195+
ens = zeros(scalartype(ψ), length(ψ))
196196
for i in 1:length(ψ)
197197
operator = AC_hamiltonian(i, ψ, O, ψ, envs)
198198
ens[i] = dot.AC[i], operator * ψ.AC[i])

src/environments/abstract_envs.jl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,52 +15,64 @@ Base.unlock(envs::AbstractMPSEnvironments) = unlock(envs.lock);
1515
# ------------------
1616
function allocate_GL(bra::AbstractMPS, mpo::AbstractMPO, ket::AbstractMPS, i::Int)
1717
T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket))
18-
TA = similarstoragetype(storagetype(mpo), T)
18+
TO = TensorKit.similarstoragetype(storagetype(mpo), T)
19+
TB = TensorKit.similarstoragetype(storagetype(bra), T)
20+
TK = TensorKit.similarstoragetype(storagetype(ket), T)
21+
TA = reduce(TensorKit.promote_storagetype, (TB, TO, TK))
1922
V = left_virtualspace(bra, i) left_virtualspace(mpo, i)'
2023
left_virtualspace(ket, i)
2124
if V isa BlockTensorKit.TensorMapSumSpace
2225
TT = blocktensormaptype(spacetype(bra), numout(V), numin(V), TA)
2326
else
24-
TT = TensorKit.TensorMapWithStorage{T, TA}
27+
TT = TensorKit.tensormaptype(spacetype(bra), numout(V), numin(V), TA)
2528
end
2629
return TT(undef, V)
2730
end
2831

2932
function allocate_GR(bra::AbstractMPS, mpo::AbstractMPO, ket::AbstractMPS, i::Int)
3033
T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket))
31-
TA = similarstoragetype(storagetype(mpo), T)
34+
TO = TensorKit.similarstoragetype(storagetype(mpo), T)
35+
TB = TensorKit.similarstoragetype(storagetype(bra), T)
36+
TK = TensorKit.similarstoragetype(storagetype(ket), T)
37+
TA = reduce(TensorKit.promote_storagetype, (TB, TO, TK))
3238
V = right_virtualspace(ket, i) right_virtualspace(mpo, i)
3339
right_virtualspace(bra, i)
3440
if V isa BlockTensorKit.TensorMapSumSpace
3541
TT = blocktensormaptype(spacetype(bra), numout(V), numin(V), TA)
3642
else
37-
TT = TensorKit.TensorMapWithStorage{T, TA}
43+
TT = TensorKit.tensormaptype(spacetype(bra), numout(V), numin(V), TA)
3844
end
3945
return TT(undef, V)
4046
end
4147

4248
function allocate_GBL(bra::QP, mpo::AbstractMPO, ket::QP, i::Int)
4349
T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket))
44-
TA = similarstoragetype(storagetype(mpo), T)
50+
TO = TensorKit.similarstoragetype(storagetype(mpo), T)
51+
TB = TensorKit.similarstoragetype(storagetype(bra), T)
52+
TK = TensorKit.similarstoragetype(storagetype(ket), T)
53+
TA = reduce(TensorKit.promote_storagetype, (TB, TO, TK))
4554
V = left_virtualspace(bra.left_gs, i) left_virtualspace(mpo, i)'
4655
auxiliaryspace(ket)' left_virtualspace(ket.right_gs, i)
4756
if V isa BlockTensorKit.TensorMapSumSpace
4857
TT = blocktensormaptype(spacetype(bra), numout(V), numin(V), TA)
4958
else
50-
TT = TensorKit.TensorMapWithStorage{T, TA}
59+
TT = TensorKit.tensormaptype(spacetype(bra), numout(V), numin(V), TA)
5160
end
5261
return TT(undef, V)
5362
end
5463

5564
function allocate_GBR(bra::QP, mpo::AbstractMPO, ket::QP, i::Int)
5665
T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket))
57-
TA = similarstoragetype(storagetype(mpo), T)
66+
TO = TensorKit.similarstoragetype(storagetype(mpo), T)
67+
TB = TensorKit.similarstoragetype(storagetype(bra), T)
68+
TK = TensorKit.similarstoragetype(storagetype(ket), T)
69+
TA = reduce(TensorKit.promote_storagetype, (TB, TO, TK))
5870
V = right_virtualspace(ket.left_gs, i) right_virtualspace(mpo, i)
5971
auxiliaryspace(ket)' right_virtualspace(bra.right_gs, i)
6072
if V isa BlockTensorKit.TensorMapSumSpace
6173
TT = blocktensormaptype(spacetype(bra), numout(V), numin(V), TA)
6274
else
63-
TT = TensorKit.TensorMapWithStorage{T, TA}
75+
TT = TensorKit.tensormaptype(spacetype(bra), numout(V), numin(V), TA)
6476
end
6577
return TT(undef, V)
6678
end

src/operators/jordanmpotensor.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ const JordanMPOTensorMap{T, S, A <: DenseVector{T}} = JordanMPOTensor{
6565
TensorMap{T, S, 1, 2, A},
6666
TensorMap{T, S, 1, 1, A},
6767
}
68+
# TODO FIX ME
69+
TensorKit.storagetype(jmpo::JordanMPOTensorMap{E, S, TA}) where {E, S, TA} = TA
70+
TensorKit.storagetype(::Type{JordanMPOTensorMap{E, S, TA}}) where {E, S, TA} = TA
6871

6972
function JordanMPOTensor{E, S}(::UndefInitializer, V::TensorMapSumSpace{S}) where {E, S}
7073
return jordanmpotensortype(S, E)(undef, V)
@@ -121,12 +124,13 @@ function JordanMPOTensor(W::SparseBlockTensorMap{TT, E, S, 2, 2}) where {TT, E,
121124
)
122125
end
123126

124-
function jordanmpotensortype(::Type{S}, ::Type{E}) where {S <: VectorSpace, E <: Number}
125-
TA = Union{tensormaptype(S, 2, 2, E), BraidingTensor{E, S}}
126-
TB = tensormaptype(S, 2, 1, E)
127-
TC = tensormaptype(S, 1, 2, E)
128-
TD = tensormaptype(S, 1, 1, E)
129-
return JordanMPOTensor{E, S, TA, TB, TC, TD}
127+
function jordanmpotensortype(::Type{S}, ::Type{TorA}) where {S <: VectorSpace, TorA}
128+
BT = BraidingTensor{eltype(TorA), S}
129+
TA = Union{tensormaptype(S, 2, 2, TorA), BT}
130+
TB = tensormaptype(S, 2, 1, TorA)
131+
TC = tensormaptype(S, 1, 2, TorA)
132+
TD = tensormaptype(S, 1, 1, TorA)
133+
return JordanMPOTensor{eltype(TorA), S, TA, TB, TC, TD}
130134
end
131135
function jordanmpotensortype(::Type{O}) where {O <: MPOTensor}
132136
return jordanmpotensortype(spacetype(O), scalartype(O))

src/operators/mpohamiltonian.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ end
4848
const InfiniteMPOHamiltonian{O <: MPOTensor} = MPOHamiltonian{O, PeriodicVector{O}}
4949
Base.isfinite(::Type{<:InfiniteMPOHamiltonian}) = false
5050
GeometryStyle(::Type{<:InfiniteMPOHamiltonian}) = InfiniteChainStyle()
51+
TensorKit.storagetype(impo::InfiniteMPOHamiltonian{O}) where {O} = storagetype(O)
52+
TensorKit.storagetype(::Type{InfiniteMPOHamiltonian{O}}) where {O} = storagetype(O)
5153

5254
function InfiniteMPOHamiltonian(Ws::AbstractVector{O}) where {O <: MPOTensor}
5355
for i in eachindex(Ws)
@@ -522,6 +524,7 @@ function InfiniteMPOHamiltonian(lattice′::AbstractArray{<:VectorSpace}, local_
522524
T = _find_tensortype(nonzero_opps)
523525
E = scalartype(T)
524526
S = spacetype(T)
527+
TA = storagetype(T)
525528

526529
# construct the virtual spaces
527530
MissingS = Union{Missing, S}
@@ -588,7 +591,7 @@ function InfiniteMPOHamiltonian(lattice′::AbstractArray{<:VectorSpace}, local_
588591
end
589592

590593
# construct the tensor
591-
TW = jordanmpotensortype(S, E)
594+
TW = jordanmpotensortype(S, TA)
592595
Os = map(1:length(lattice)) do site
593596
V = virtualsumspaces[site - 1] * lattice[site]
594597
lattice[site] * virtualsumspaces[site]

src/states/abstractmps.jl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ Construct an `MPSTensor` with given physical and virtual spaces.
3434
"""
3535
function MPSTensor(
3636
::UndefInitializer, ::Type{TorA}, P::Union{S, CompositeSpace{S}}, Vₗ::S, Vᵣ::S = Vₗ
37-
) where {S <: ElementarySpace, TorA}
38-
return TensorKit.TensorMapWithStorage{TorA}(undef, Vₗ P Vᵣ)
37+
) where {S <: ElementarySpace, TorA <: Number}
38+
return TensorKit.TensorMap{TorA}(undef, Vₗ P Vᵣ)
39+
end
40+
function MPSTensor(
41+
::UndefInitializer, ::Type{TorA}, P::Union{S, CompositeSpace{S}}, Vₗ::S, Vᵣ::S = Vₗ
42+
) where {S <: ElementarySpace, TorA <: DenseVector}
43+
return TensorKit.TensorMapWithStorage{eltype(TorA), TorA}(undef, Vₗ P Vᵣ)
3944
end
4045
function MPSTensor(
4146
f, ::Type{TorA}, P::Union{S, CompositeSpace{S}}, Vₗ::S, Vᵣ::S = Vₗ
@@ -51,6 +56,12 @@ function MPSTensor(
5156
throw(ArgumentError("Unsupported initializer function: $f"))
5257
end
5358
end
59+
function MPSTensor(
60+
::Type{TorA},
61+
P::Union{S, CompositeSpace{S}}, Vₗ::S, Vᵣ::S = Vₗ
62+
) where {S <: ElementarySpace, TorA}
63+
return MPSTensor(rand, TorA, P, Vₗ, Vᵣ)
64+
end
5465
# TODO: reinstate function initializers?
5566
function MPSTensor(
5667
P::Union{S, CompositeSpace{S}}, Vₗ::S, Vᵣ::S = Vₗ
@@ -78,11 +89,11 @@ MPSTensor(d::Int, Dₗ::Int; Dᵣ::Int = Dₗ) = MPSTensor(ℂ^d, ℂ^Dₗ, ℂ^
7889
7990
Convert an array to an `MPSTensor`.
8091
"""
81-
function MPSTensor(A::AA) where {T <: Number, AA <: AbstractArray{T}}
92+
function MPSTensor(A::AbstractArray{<:Number})
8293
@assert ndims(A) > 2 "MPSTensor should have at least 3 dims, but has $ndims(A)"
8394
sz = size(A)
84-
t = TensorKit.TensorMapWithStorage{T, AA}(undef, foldl(, ComplexSpace.(sz[1:(end - 1)])) ^sz[end])
85-
t[] .= A
95+
V = foldl(, ComplexSpace.(sz[1:(end - 1)])) ^sz[end]
96+
t = TensorMap(A, V)
8697
return t
8798
end
8899

src/states/infinitemps.jl

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ struct InfiniteMPS{A <: GenericMPSTensor, B <: MPSBondTensor} <: AbstractMPS
102102
return new{A, B}(AL, AR, C, AC)
103103
end
104104
end
105+
TensorKit.storagetype(imps::InfiniteMPS{A, B}) where {A, B} = storagetype(A)
106+
TensorKit.storagetype(::Type{InfiniteMPS{A, B}}) where {A, B} = storagetype(A)
105107

106108
#===========================================================================================
107109
Constructors
@@ -116,35 +118,42 @@ function InfiniteMPS(
116118
convert(PeriodicVector{B}, C), convert(PeriodicVector{A}, AC)
117119
)
118120
end
119-
120121
function InfiniteMPS(
122+
::Type{TorA},
121123
pspaces::AbstractVector{S}, Dspaces::AbstractVector{S};
122124
kwargs...
123-
) where {S <: IndexSpace}
124-
return InfiniteMPS(MPSTensor.(pspaces, circshift(Dspaces, 1), Dspaces); kwargs...)
125+
) where {S <: IndexSpace, TorA}
126+
return InfiniteMPS(MPSTensor.(TorA, pspaces, circshift(Dspaces, 1), Dspaces); kwargs...)
125127
end
126128
function InfiniteMPS(
127-
f, elt::Type{<:Number}, pspaces::AbstractVector{S}, Dspaces::AbstractVector{S};
129+
pspaces::AbstractVector{S}, Dspaces::AbstractVector{S};
128130
kwargs...
129131
) where {S <: IndexSpace}
132+
return InfiniteMPS(MPSTensor.(ComplexF64, pspaces, circshift(Dspaces, 1), Dspaces); kwargs...)
133+
end
134+
function InfiniteMPS(
135+
f, ::Type{TorA}, pspaces::AbstractVector{S}, Dspaces::AbstractVector{S};
136+
kwargs...
137+
) where {S <: IndexSpace, TorA}
130138
return InfiniteMPS(
131-
MPSTensor.(f, elt, pspaces, circshift(Dspaces, 1), Dspaces);
139+
MPSTensor.(f, TorA, pspaces, circshift(Dspaces, 1), Dspaces);
132140
kwargs...
133141
)
134142
end
135-
InfiniteMPS(d::S, D::S) where {S <: Union{Int, <:IndexSpace}} = InfiniteMPS([d], [D])
143+
InfiniteMPS(::Type{TorA}, d::S, D::S; kwargs...) where {S <: Union{Int, <:IndexSpace}, TorA} = InfiniteMPS(TorA, [d], [D]; kwargs...)
144+
InfiniteMPS(d::S, D::S; kwargs...) where {S <: Union{Int, <:IndexSpace}} = InfiniteMPS([d], [D]; kwargs...)
136145
function InfiniteMPS(
137-
f, elt::Type{<:Number}, d::S, D::S
138-
) where {S <: Union{Int, <:IndexSpace}}
139-
return InfiniteMPS(f, elt, [d], [D])
146+
f, ::Type{TorA}, d::S, D::S; kwargs...
147+
) where {S <: Union{Int, <:IndexSpace}, TorA}
148+
return InfiniteMPS(f, TorA, [d], [D]; kwargs...)
140149
end
141-
function InfiniteMPS(ds::AbstractVector{Int}, Ds::AbstractVector{Int})
142-
return InfiniteMPS(ComplexSpace.(ds), ComplexSpace.(Ds))
150+
function InfiniteMPS(ds::AbstractVector{Int}, Ds::AbstractVector{Int}; kwargs...)
151+
return InfiniteMPS(ComplexSpace.(ds), ComplexSpace.(Ds); kwargs...)
143152
end
144153
function InfiniteMPS(
145-
f, elt::Type{<:Number}, ds::AbstractVector{Int}, Ds::AbstractVector{Int}, kwargs...
146-
)
147-
return InfiniteMPS(f, elt, ComplexSpace.(ds), ComplexSpace.(Ds); kwargs...)
154+
f, ::Type{TorA}, ds::AbstractVector{Int}, Ds::AbstractVector{Int}, kwargs...
155+
) where {TorA}
156+
return InfiniteMPS(f, TorA, ComplexSpace.(ds), ComplexSpace.(Ds); kwargs...)
148157
end
149158

150159
function InfiniteMPS(A::AbstractVector{<:GenericMPSTensor}; kwargs...)

0 commit comments

Comments
 (0)