From 86307ae65b98f8364c18e5dfce48d76b774b2b7e Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 14 Oct 2026 05:20:34 -0400 Subject: [PATCH 1/9] allow various objects to accept a storagetype or pass it along --- src/algorithms/ctmrg/gaugefix.jl | 6 ++--- src/algorithms/ctmrg/initialization.jl | 10 +++---- src/algorithms/time_evolution/gaugefix_su.jl | 4 +-- .../time_evolution/simpleupdate3site.jl | 4 +-- src/algorithms/time_evolution/time_evolve.jl | 2 +- src/algorithms/time_evolution/trotter_gate.jl | 4 ++- src/algorithms/toolbox.jl | 2 +- src/environments/bp_environments.jl | 8 +++--- .../product_state_environments.jl | 6 ++--- src/environments/suweight.jl | 26 ++++++++++++------- src/environments/vumps_environments.jl | 6 +++-- src/networks/tensors.jl | 17 +++++++----- src/operators/infinitepepo.jl | 2 +- src/operators/transfermatrix.jl | 26 +++++++++---------- src/states/infinitepeps.jl | 6 ++--- 15 files changed, 72 insertions(+), 57 deletions(-) diff --git a/src/algorithms/ctmrg/gaugefix.jl b/src/algorithms/ctmrg/gaugefix.jl index 6ff44e554..9c5c73d78 100644 --- a/src/algorithms/ctmrg/gaugefix.jl +++ b/src/algorithms/ctmrg/gaugefix.jl @@ -82,7 +82,7 @@ function compute_relative_phases( # Random MPS of same bond dimension M = map(Tsfinal) do t - randn(scalartype(t), codomain(t) ← domain(t)) + randn(storagetype(T), codomain(t) ← domain(t)) end # Find right fixed points of mixed transfer matrices @@ -107,7 +107,7 @@ function compute_relative_phases(envfinal::CTMRGEnv{C, T}, envprev::CTMRGEnv{C, # Random Hermitian MPS of same bond dimension # (make Hermitian such that T-M transfer matrix has real eigenvalues) - M = _project_hermitian(randn(scalartype(Tfinal), space(Tfinal))) + M = _project_hermitian(randn(storagetype(Tfinal), space(Tfinal))) # Find right fixed points of mixed transfer matrices eigsolve_alg = Lanczos() # real eigenvalues @@ -145,7 +145,7 @@ end function initialize_right_fixedpoint(tops, bottoms) ρ0 = randn( - scalartype(tops), space(tops[end], numind(tops[end]))' ← space(bottoms[end], numind(bottoms[end]))' + TensorKit.promote_storagetype(tops...), space(tops[end], numind(tops[end]))' ← space(bottoms[end], numind(bottoms[end]))' ) return ρ0 end diff --git a/src/algorithms/ctmrg/initialization.jl b/src/algorithms/ctmrg/initialization.jl index 235611e0b..c44f04826 100644 --- a/src/algorithms/ctmrg/initialization.jl +++ b/src/algorithms/ctmrg/initialization.jl @@ -5,7 +5,7 @@ Initialize a fully random `CTMRGEnv` using the given environment virtual spaces. [`CTMRGEnv`](@ref) for details on the expected format of the virtual spaces. """ function initialize_ctmrg_environment( - elt::Type{<:Number}, + elt::Type, n::InfiniteSquareNetwork, alg::RandomInitialization, virtual_spaces... = oneunit(spacetype(n)), @@ -20,7 +20,7 @@ Initialize a `CTMRGEnv` corresponding to a product state with trivial virtual sp corners. The product state edge tensors are initialized as `alg.f(elt, V::ProductSpace)`. """ function initialize_ctmrg_environment( - elt::Type{<:Number}, + elt::Type, n::InfiniteSquareNetwork, alg::ProductStateInitialization, ) @@ -36,7 +36,7 @@ Initialize a `CTMRGEnv` by applying a single untruncated iteration of environment is chosen as a random product state. """ function initialize_ctmrg_environment( - elt::Type{<:Number}, + elt::Type, n::InfiniteSquareNetwork, alg::ApplicationInitialization, env0 = ProductStateEnv(alg.f, elt, n) @@ -65,7 +65,7 @@ virtual spaces of a two-layer network, for example ``` """ function initialize_ctmrg_environment( - elt::Type{<:Number}, + elt::Type, n::InfiniteSquareNetwork, ::IdentityInitialization, ) @@ -86,5 +86,5 @@ function initialize_ctmrg_environment( elt::Type{<:Number}, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; kwargs... ) - return initialize_ctmrg_environment(elt, InfiniteSquareNetwork(A), args...; kwargs...) + return initialize_ctmrg_environment(similarstoragetype(storagetype(A), elt), InfiniteSquareNetwork(A), args...; kwargs...) end diff --git a/src/algorithms/time_evolution/gaugefix_su.jl b/src/algorithms/time_evolution/gaugefix_su.jl index 13a2782d6..a373d773d 100644 --- a/src/algorithms/time_evolution/gaugefix_su.jl +++ b/src/algorithms/time_evolution/gaugefix_su.jl @@ -17,7 +17,7 @@ $(TYPEDFIELDS) maxiter::Int = 100 end -function _trivial_gates(elt::Type{<:Number}, lattice::Matrix{S}) where {S <: ElementarySpace} +function _trivial_gates(elt::Type, lattice::Matrix{S}) where {S <: ElementarySpace} Nr, Nc = size(lattice) gates = map(Iterators.product(1:2, 1:Nc, 1:Nr)) do (d, c, r) site1 = CartesianIndex(r, c) @@ -38,7 +38,7 @@ Fix the gauge of `psi` using trivial simple update. """ function gauge_fix(psi::InfiniteState, alg::SUGauge) time0 = time() - gates = _trivial_gates(scalartype(psi), physicalspace(psi)) + gates = _trivial_gates(storagetype(psi), physicalspace(psi)) trunc = _get_fixedspacetrunc(psi) su_alg = SimpleUpdate(; trunc, bipartite = _is_bipartite(psi)) wts0 = SUWeight(psi) diff --git a/src/algorithms/time_evolution/simpleupdate3site.jl b/src/algorithms/time_evolution/simpleupdate3site.jl index da79055e2..2b5b87673 100644 --- a/src/algorithms/time_evolution/simpleupdate3site.jl +++ b/src/algorithms/time_evolution/simpleupdate3site.jl @@ -1,6 +1,6 @@ function _fuse_physicalspaces(O::GenericMPSTensor{S, 5}) where {S <: ElementarySpace} V1, V2 = codomain(O, 2), codomain(O, 3) - F = isomorphism(Int, fuse(V1, V2), V1 ⊗ V2) + F = isomorphism(similarstoragetype(O, Int), fuse(V1, V2), V1 ⊗ V2) @plansor O_fused[-1 -2 -4 -5; -6] := F[-2; 2 3] * O[-1 2 3 -4 -5; -6] return O_fused, F end @@ -8,7 +8,7 @@ end function _unfuse_physicalspace( O::GenericMPSTensor{S, 4}, Vout::ElementarySpace, Vin::ElementarySpace = Vout' ) where {S <: ElementarySpace} - F = isomorphism(Int, Vout ⊗ Vin, fuse(Vout ⊗ Vin)) + F = isomorphism(similarstoragetype(O, Int), Vout ⊗ Vin, fuse(Vout ⊗ Vin)) @plansor O_unfused[-1 -2 -3 -4 -5; -6] := F[-2 -3; 1] * O[-1 1 -4 -5; -6] return O_unfused, F end diff --git a/src/algorithms/time_evolution/time_evolve.jl b/src/algorithms/time_evolution/time_evolve.jl index c1dc32233..d6065d20a 100644 --- a/src/algorithms/time_evolution/time_evolve.jl +++ b/src/algorithms/time_evolution/time_evolve.jl @@ -69,7 +69,7 @@ function _timeevol_sanity_check( end function MPSKit.infinite_temperature_density_matrix(H::LocalOperator) - T = scalartype(H) + T = storagetype(H) A = map(physicalspace(H)) do Vp ψ = permute(TensorKit.id(T, Vp), (1, 2)) Vv = oneunit(Vp) # trivial (1D) virtual space diff --git a/src/algorithms/time_evolution/trotter_gate.jl b/src/algorithms/time_evolution/trotter_gate.jl index c4a52bfd5..7d20f40ab 100644 --- a/src/algorithms/time_evolution/trotter_gate.jl +++ b/src/algorithms/time_evolution/trotter_gate.jl @@ -157,7 +157,9 @@ function _trotterize_nnn2site!(gates::Vector, H::LocalOperator, dt::Number) term = permute(term, ((2, 1), (4, 3))) end gate = gate_to_mpo(exp(term * -dt / 2)) - b = TensorKit.BraidingTensor{T}(physicalspace(H, x2), left_virtualspace(gate[2])) + A = similarstoragetype(term, T) + S = spacetype(TensorKit.promote(physicalspace(H, x2), left_virtualspace(gate[2]))[1]) + b = TensorKit.BraidingTensor{T, S, A}(physicalspace(H, x2), left_virtualspace(gate[2])) insert!(gate, 2, TensorMap(b)) push!(gates, [x1, x2, x3] => gate) end diff --git a/src/algorithms/toolbox.jl b/src/algorithms/toolbox.jl index 533fac679..b825b2f80 100644 --- a/src/algorithms/toolbox.jl +++ b/src/algorithms/toolbox.jl @@ -13,7 +13,7 @@ function edge_transfer_spectrum( sector = one(sectortype(E)) ) where {E <: CTMRGEdgeTensor} init = randn( - scalartype(E), + storagetype(E), space(first(bot), numind(first(bot)))' ← ℂ[typeof(sector)](sector => 1)' ⊗ space(first(top), 1), ) diff --git a/src/environments/bp_environments.jl b/src/environments/bp_environments.jl index 70460f721..85efd256d 100644 --- a/src/environments/bp_environments.jl +++ b/src/environments/bp_environments.jl @@ -119,13 +119,13 @@ Construct a BP environment by specifying a corresponding [`InfiniteSquareNetwork function BPEnv(f, T, network::InfiniteSquareNetwork; posdef::Bool = true) Ds_north = _north_edge_physical_spaces(network) Ds_east = _east_edge_physical_spaces(network) - return BPEnv(f, T, Ds_north, Ds_east; posdef) + return BPEnv(f, similarstoragetype(storagetype(network), eltype(T)), Ds_north, Ds_east; posdef) end function BPEnv(network::Union{InfiniteSquareNetwork, InfinitePartitionFunction, InfinitePEPS, InfinitePEPO}, args...; kwargs...) - return BPEnv(isomorphism, scalartype(network), network, args...; kwargs...) + return BPEnv(isomorphism, storagetype(network), network, args...; kwargs...) end function BPEnv(f, T, state::Union{InfinitePartitionFunction, InfinitePEPS, InfinitePEPO}, args...; kwargs...) - return BPEnv(f, T, InfiniteSquareNetwork(state), args...; kwargs...) + return BPEnv(f, similarstoragetype(eltype(state), eltype(T)), InfiniteSquareNetwork(state), args...; kwargs...) end Base.eltype(::Type{BPEnv{T}}) where {T} = T @@ -173,7 +173,7 @@ function CTMRGEnv(bp_env::BPEnv) return insertleftunit(insertleftunit(M), 1) end corners = map(CartesianIndices(edges)) do _ - return TensorKit.id(scalartype(bp_env), oneunit(spacetype(bp_env))) + return TensorKit.id(storagetype(bp_env), oneunit(spacetype(bp_env))) end return CTMRGEnv(corners, edges) end diff --git a/src/environments/product_state_environments.jl b/src/environments/product_state_environments.jl index 394bc5751..93a1577b9 100644 --- a/src/environments/product_state_environments.jl +++ b/src/environments/product_state_environments.jl @@ -82,13 +82,13 @@ Construct a product state environment by specifying a corresponding [`InfiniteSq function ProductStateEnv(f, T, network::InfiniteSquareNetwork) Ds_north = _north_edge_physical_spaces(network) Ds_east = _east_edge_physical_spaces(network) - return ProductStateEnv(f, T, Ds_north, Ds_east) + return ProductStateEnv(f, similarstoragetype(storagetype(network), eltype(T)), Ds_north, Ds_east) end function ProductStateEnv(network::Union{InfiniteSquareNetwork, InfinitePartitionFunction, InfinitePEPS}) - return ProductStateEnv(randn, scalartype(network), network) + return ProductStateEnv(randn, storagetype(network), network) end function ProductStateEnv(f, T, state::Union{InfinitePartitionFunction, InfinitePEPS}, args...) - return ProductStateEnv(f, T, InfiniteSquareNetwork(state), args...) + return ProductStateEnv(f, similarstoragetype(eltype(state), eltype(T)), InfiniteSquareNetwork(state), args...) end Base.eltype(::Type{ProductStateEnv{T}}) where {T} = T diff --git a/src/environments/suweight.jl b/src/environments/suweight.jl index 3ccd5ba38..8956f470f 100644 --- a/src/environments/suweight.jl +++ b/src/environments/suweight.jl @@ -58,32 +58,40 @@ function SUWeight(wts_mats::AbstractMatrix{E}...) where {E <: PEPSWeight} end """ - SUWeight(Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:ElementarySpace}} + SUWeight(T, Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:ElementarySpace}} Create a trivial `SUWeight` by specifying the vertical (north) or horizontal (east) virtual bond spaces. +`T` is either a scalar type (like `ComplexF32`) or an array type (like `Vector{Float64}`) that +specifies the storage type. If `T <: Number` the default storage type is `Vector{T}`. """ function SUWeight( + T, Nspaces::M, Espaces::M = Nspaces ) where {M <: AbstractMatrix{<:ElementarySpace}} @assert size(Nspaces) == size(Espaces) Nr, Nc = size(Nspaces) weights = map(Iterators.product(1:2, 1:Nr, 1:Nc)) do (d, r, c) V = (d == 1 ? Espaces[r, c] : Nspaces[r, c]) - DiagonalTensorMap(ones(reduceddim(V)), V) + realT = similarstoragetype(T, real(eltype(T))) + diag = realT(undef, reduceddim(V)) + fill!(diag, real(eltype(T))) + DiagonalTensorMap(diag, V) end return SUWeight(weights) end """ - SUWeight(Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1)) where {S<:ElementarySpace} + SUWeight(T, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1)) where {S<:ElementarySpace} Create a trivial `SUWeight` by specifying its vertical (north) and horizontal (east) -as `ElementarySpace`s) and unit cell size. +as `ElementarySpace`s) and unit cell size. `T` is either a scalar type (like `ComplexF32`) +or an array type (like `Vector{Float64}`) that specifies the storage type. +If `T <: Number` the default storage type is `Vector{T}`. """ function SUWeight( - Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + T, Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) ) where {S <: ElementarySpace} - return SUWeight(fill(Nspace, unitcell), fill(Espace, unitcell)) + return SUWeight(T, fill(Nspace, unitcell), fill(Espace, unitcell)) end """ @@ -94,7 +102,7 @@ Create a trivial `SUWeight` for a given InfinitePEPS. function SUWeight(peps::InfinitePEPS) Nspaces = map(Base.Fix2(domain, NORTH), unitcell(peps)) Espaces = map(Base.Fix2(domain, EAST), unitcell(peps)) - return SUWeight(Nspaces, Espaces) + return SUWeight(storagetype(peps), Nspaces, Espaces) end """ @@ -106,7 +114,7 @@ function SUWeight(pepo::InfinitePEPO) @assert size(pepo, 3) == 1 Nspaces = map(Base.Fix2(domain, NORTH), @view(unitcell(pepo)[:, :, 1])) Espaces = map(Base.Fix2(domain, EAST), @view(unitcell(pepo)[:, :, 1])) - return SUWeight(Nspaces, Espaces) + return SUWeight(storagetype(pepo), Nspaces, Espaces) end Random.rand!(wts::SUWeight) = rand!(Random.default_rng(), wts) @@ -329,7 +337,7 @@ which has the same real scalartype as ``wts`. """ function CTMRGEnv(wts::SUWeight) _, Nr, Nc = size(wts) - elt = scalartype(wts) + elt = storagetype(wts) V_env = oneunit(spacetype(wts)) edges = map(Iterators.product(1:4, 1:Nr, 1:Nc)) do (d, r, c) wt_idx = if d == NORTH diff --git a/src/environments/vumps_environments.jl b/src/environments/vumps_environments.jl index 48605f2f1..6ef0375d0 100644 --- a/src/environments/vumps_environments.jl +++ b/src/environments/vumps_environments.jl @@ -25,10 +25,11 @@ function MPSKit.allocate_GL( bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int ) T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket)) + TA = similarstoragetype(storagetype(mpo), T) V = left_virtualspace(bra, i) ⊗ _elementwise_dual(left_virtualspace(mpo, i)) ← left_virtualspace(ket, i) - TT = TensorMap{T} + TT = TensorKit.TensorMapWithStorage{T, TA} return TT(undef, V) end @@ -36,7 +37,8 @@ function MPSKit.allocate_GR( bra::InfiniteMPS, mpo::InfiniteTransferMatrix, ket::InfiniteMPS, i::Int ) T = Base.promote_type(scalartype(bra), scalartype(mpo), scalartype(ket)) + TA = similarstoragetype(storagetype(mpo), T) V = right_virtualspace(ket, i) ⊗ right_virtualspace(mpo, i) ← right_virtualspace(bra, i) - TT = TensorMap{T} + TT = TensorKit.TensorMapWithStorage{T, TA} return TT(undef, V) end diff --git a/src/networks/tensors.jl b/src/networks/tensors.jl index 6ac6411da..347860366 100644 --- a/src/networks/tensors.jl +++ b/src/networks/tensors.jl @@ -24,10 +24,11 @@ const PFTensor = PartitionFunctionTensor """ PartitionFunctionTensor(f, ::Type{T}, Pspace::S, Nspace::S, - [Espace::S], [Sspace::S], [Wspace::S]) where {T,S<:Union{Int,ElementarySpace}} + [Espace::S], [Sspace::S], [Wspace::S]) where {T, S<:Union{Int,ElementarySpace}} -Construct a PartitionFunctionTensor tensor based on the north, east, west and south spaces. -The tensor elements are generated based on `f` and the element type is specified in `T`. +Construct a `PartitionFunctionTensor` tensor based on the north, east, west and south spaces. +The tensor elements are generated based on `f` and the element type and storage type is +specified in `T`. """ function PartitionFunctionTensor( f, ::Type{T}, @@ -80,13 +81,15 @@ const PEPSTensor{S <: ElementarySpace} = AbstractTensorMap{<:Any, S, 1, 4} """ PEPSTensor(f, ::Type{T}, Pspace::S, Nspace::S, - [Espace::S], [Sspace::S], [Wspace::S]) where {T,S<:Union{Int,ElementarySpace}} + [Espace::S], [Sspace::S], [Wspace::S]) where {T, S<:Union{Int,ElementarySpace}} Construct a PEPS tensor based on the physical, north, east, south and west spaces. -The tensor elements are generated based on `f` and the element type is specified in `T`. +The tensor elements are generated based on `f` and the element type and storage type +is specified in `T`. """ function PEPSTensor( - f, ::Type{T}, + f, + ::Type{T}, Pspace::S, Nspace::S, Espace::S = Nspace, Sspace::S = Nspace', Wspace::S = Espace', ) where {T, S <: ElementarySpace} @@ -155,7 +158,7 @@ herm_depth(t::PEPOTensor) = permute(t', ((5, 6), (3, 2, 1, 4))) Fuse the physical indices of a PEPO tensor, obtaining a PEPS tensor. """ function fuse_physicalspaces(O::PEPOTensor) - F = isomorphism(Int, fuse(codomain(O)), codomain(O)) + F = isomorphism(TensorKit.similarstoragetype(O, Int), fuse(codomain(O)), codomain(O)) return F * O, F end diff --git a/src/operators/infinitepepo.jl b/src/operators/infinitepepo.jl index f902a3874..1f68a9161 100644 --- a/src/operators/infinitepepo.jl +++ b/src/operators/infinitepepo.jl @@ -121,7 +121,7 @@ function initializePEPS( end Nspaces = repeat([vspace], size(T, 1), size(T, 2)) Espaces = repeat([vspace], size(T, 1), size(T, 2)) - return InfinitePEPS(Pspaces, Nspaces, Espaces) + return InfinitePEPS(randn, storagetype(T), Pspaces, Nspaces, Espaces) end ## Unit cell interface diff --git a/src/operators/transfermatrix.jl b/src/operators/transfermatrix.jl index 85199a75f..e9b59723a 100644 --- a/src/operators/transfermatrix.jl +++ b/src/operators/transfermatrix.jl @@ -130,13 +130,13 @@ virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir) """ initialize_mps( f=randn, - T=scalartype(O), + T=storagetype(O), O::Union{InfiniteTransferPEPS,InfiniteTransferPEPO}, virtualspaces::AbstractArray{<:ElementarySpace,1} ) initialize_mps( f=randn, - T=scalartype(O), + T=storagetype(O), O::Union{MultilineTransferPEPS,MultilineTransferPEPO}, virtualspaces::AbstractArray{<:ElementarySpace,2} ) @@ -144,12 +144,12 @@ virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir) Inialize a boundary MPS for the transfer operator `O` by specifying an array of virtual spaces consistent with the unit cell. """ -function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix}, arg) # initialize(f=randn, T=scalartype(O), O, ...) - return initialize_mps(randn, scalartype(O), O, arg) +function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix}, arg; kwargs...) # initialize(f=randn, T=scalartype(O), O, ...) + return initialize_mps(randn, storagetype(O), O, arg; kwargs...) end function initialize_mps( - f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S, 1} - ) where {S} + f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S, 1}; kwargs... + ) where {T} return InfiniteMPS( [ f( @@ -157,24 +157,24 @@ function initialize_mps( virtualspaces[_prev(i, end)] * _elementwise_dual(north_virtualspace(O, i)), virtualspaces[mod1(i, end)], ) for i in 1:length(O) - ] + ]; kwargs... ) end function initialize_mps( - f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 2} + f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 2}; kwargs... ) where {S} mpss = map(1:size(O, 1)) do r - return initialize_mps(f, T, O[r], virtualspaces[r, :]) + return initialize_mps(f, T, O[r], virtualspaces[r, :]; kwargs...) end return MPSKit.Multiline(mpss) end function initialize_mps( - f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 1} + f, T, O::MultilineTransferMatrix, virtualspaces::AbstractArray{S, 1}; kwargs... ) where {S} - return initialize_mps(f, T, O, repeat(virtualspaces, length(O), 1)) + return initialize_mps(f, T, O, repeat(virtualspaces, length(O), 1); kwargs...) end -function initialize_mps(f, T, O::MultilineTransferMatrix, V::ElementarySpace) - return initialize_mps(f, T, O, repeat([V], length(O), length(O[1]))) +function initialize_mps(f, T, O::MultilineTransferMatrix, V::ElementarySpace; kwargs...) + return initialize_mps(f, T, O, repeat([V], length(O), length(O[1])); kwargs...) end @doc """ diff --git a/src/states/infinitepeps.jl b/src/states/infinitepeps.jl index 3d3a82f0f..6870dd3a9 100644 --- a/src/states/infinitepeps.jl +++ b/src/states/infinitepeps.jl @@ -46,7 +46,7 @@ Create an `InfinitePEPS` by specifying the physical, north virtual and east virt of the PEPS tensor at each site in the unit cell as a matrix. """ function InfinitePEPS( - f, T::Type{<:Number}, Pspaces::M, Nspaces::M, Espaces::M = Nspaces + f, T, Pspaces::M, Nspaces::M, Espaces::M = Nspaces ) where {M <: AbstractMatrix{<:ElementarySpace}} size(Pspaces) == size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -108,7 +108,7 @@ end Create an InfinitePEPS by specifying its physical, north and east spaces and unit cell. """ function InfinitePEPS( - f, T::Type{<:Number}, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) + f, T, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) ) where {S <: ElementarySpace} return InfinitePEPS( f, T, @@ -126,7 +126,7 @@ Base.eltype(::Type{InfinitePEPS{T}}) where {T} = T Base.eltype(A::InfinitePEPS) = eltype(typeof(A)) Base.copy(A::InfinitePEPS) = InfinitePEPS(copy(unitcell(A))) -function Base.similar(A::InfinitePEPS, T::Type{TorA} = scalartype(A)) where {TorA} +function Base.similar(A::InfinitePEPS, T::Type = scalartype(A)) return InfinitePEPS(map(t -> similar(t, T), unitcell(A))) end Base.repeat(A::InfinitePEPS, counts...) = InfinitePEPS(repeat(unitcell(A), counts...)) From e6c8332f31c76ba72b53edd584a0e9a8cad1352e Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 14 Oct 2026 09:23:50 -0400 Subject: [PATCH 2/9] Fix precompilation --- src/operators/transfermatrix.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/transfermatrix.jl b/src/operators/transfermatrix.jl index e9b59723a..e243e1656 100644 --- a/src/operators/transfermatrix.jl +++ b/src/operators/transfermatrix.jl @@ -149,7 +149,7 @@ function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix end function initialize_mps( f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S, 1}; kwargs... - ) where {T} + ) where {S} return InfiniteMPS( [ f( From 6744709966c7f8b6b7d0d5966696079ed3a24898 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 14 Oct 2026 09:52:32 -0400 Subject: [PATCH 3/9] Formatter --- src/operators/transfermatrix.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/transfermatrix.jl b/src/operators/transfermatrix.jl index e243e1656..7280a9dfc 100644 --- a/src/operators/transfermatrix.jl +++ b/src/operators/transfermatrix.jl @@ -149,7 +149,7 @@ function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix end function initialize_mps( f, T, O::InfiniteTransferMatrix, virtualspaces::AbstractArray{S, 1}; kwargs... - ) where {S} + ) where {S} return InfiniteMPS( [ f( From 559df7b034984cc7db96f28b849a8251235a71c6 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 14 Oct 2026 13:21:38 -0400 Subject: [PATCH 4/9] Missing one --- src/environments/suweight.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/environments/suweight.jl b/src/environments/suweight.jl index 8956f470f..29787e157 100644 --- a/src/environments/suweight.jl +++ b/src/environments/suweight.jl @@ -74,7 +74,7 @@ function SUWeight( V = (d == 1 ? Espaces[r, c] : Nspaces[r, c]) realT = similarstoragetype(T, real(eltype(T))) diag = realT(undef, reduceddim(V)) - fill!(diag, real(eltype(T))) + fill!(diag, one(real(eltype(T)))) DiagonalTensorMap(diag, V) end return SUWeight(weights) From e9415a1dd16961c9095eedb256a977639e117963 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 14 Oct 2026 14:26:03 -0400 Subject: [PATCH 5/9] Some comments --- src/algorithms/time_evolution/trotter_gate.jl | 2 +- src/environments/suweight.jl | 12 ++++++++++++ src/states/infinitepeps.jl | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/algorithms/time_evolution/trotter_gate.jl b/src/algorithms/time_evolution/trotter_gate.jl index 7d20f40ab..9503ca4d2 100644 --- a/src/algorithms/time_evolution/trotter_gate.jl +++ b/src/algorithms/time_evolution/trotter_gate.jl @@ -158,7 +158,7 @@ function _trotterize_nnn2site!(gates::Vector, H::LocalOperator, dt::Number) end gate = gate_to_mpo(exp(term * -dt / 2)) A = similarstoragetype(term, T) - S = spacetype(TensorKit.promote(physicalspace(H, x2), left_virtualspace(gate[2]))[1]) + S = spacetype(H) b = TensorKit.BraidingTensor{T, S, A}(physicalspace(H, x2), left_virtualspace(gate[2])) insert!(gate, 2, TensorMap(b)) push!(gates, [x1, x2, x3] => gate) diff --git a/src/environments/suweight.jl b/src/environments/suweight.jl index 29787e157..a508cf070 100644 --- a/src/environments/suweight.jl +++ b/src/environments/suweight.jl @@ -94,6 +94,18 @@ function SUWeight( return SUWeight(T, fill(Nspace, unitcell), fill(Espace, unitcell)) end +""" + SUWeight(Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1)) where {S<:ElementarySpace} + +Create a trivial `SUWeight` by specifying its vertical (north) and horizontal (east) +as `ElementarySpace`s) and unit cell size. +""" +function SUWeight( + Nspace::S, Espace::S = Nspace; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpace} + return SUWeight(ComplexF64, fill(Nspace, unitcell), fill(Espace, unitcell)) +end + """ SUWeight(peps::InfinitePEPS) diff --git a/src/states/infinitepeps.jl b/src/states/infinitepeps.jl index 6870dd3a9..c607ae3c8 100644 --- a/src/states/infinitepeps.jl +++ b/src/states/infinitepeps.jl @@ -126,7 +126,7 @@ Base.eltype(::Type{InfinitePEPS{T}}) where {T} = T Base.eltype(A::InfinitePEPS) = eltype(typeof(A)) Base.copy(A::InfinitePEPS) = InfinitePEPS(copy(unitcell(A))) -function Base.similar(A::InfinitePEPS, T::Type = scalartype(A)) +function Base.similar(A::InfinitePEPS, T::Type = storagetype(A)) return InfinitePEPS(map(t -> similar(t, T), unitcell(A))) end Base.repeat(A::InfinitePEPS, counts...) = InfinitePEPS(repeat(unitcell(A), counts...)) From 3873b29ac3b24214a1b1d2a0bbc83d285e86f0a7 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 15 Oct 2026 02:52:16 -0400 Subject: [PATCH 6/9] Fix ambiguity warning --- src/states/infinitepeps.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/states/infinitepeps.jl b/src/states/infinitepeps.jl index c607ae3c8..d650b3e09 100644 --- a/src/states/infinitepeps.jl +++ b/src/states/infinitepeps.jl @@ -108,8 +108,8 @@ end Create an InfinitePEPS by specifying its physical, north and east spaces and unit cell. """ function InfinitePEPS( - f, T, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) - ) where {S <: ElementarySpace} + f, ::Type{T}, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) + ) where {T <: Union{Number, AbstractArray{<:Number}}, S <: ElementarySpace} return InfinitePEPS( f, T, _fill_state_physical_spaces(Pspace; unitcell), From 32d8b461e0f0316c14566e2c96a133f46b80a188 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 15 Oct 2026 08:20:27 -0400 Subject: [PATCH 7/9] Comments --- Project.toml | 2 +- docs/src/changelog.md | 2 ++ src/algorithms/ctmrg/initialization.jl | 4 ++-- src/environments/bp_environments.jl | 2 +- src/environments/suweight.jl | 6 ++++-- src/operators/transfermatrix.jl | 2 +- src/states/infinitepeps.jl | 6 +++--- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Project.toml b/Project.toml index 0dfbe5e4d..c73ef4802 100644 --- a/Project.toml +++ b/Project.toml @@ -45,7 +45,7 @@ OptimKit = "0.5" Printf = "1" Random = "1" Statistics = "1" -TensorKit = "0.16.5, 0.17" +TensorKit = "0.17" TensorKitTensors = "0.3.1" TensorOperations = "5" TupleTools = "1.6.0" diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 75e876381..7196cfa2a 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -32,6 +32,8 @@ When releasing a new version, move the "Unreleased" changes to a new version sec ### Fixed +- `initializePEPS` now returns a real-valued PEPS if given a real-valued input PEPO, rather than always returning a complex-valued PEPS + ### Performance ## [0.8.1](https://github.com/quantumkithub/pepskit.jl/compare/v0.8.0...v0.8.1) - 2026-07-30 diff --git a/src/algorithms/ctmrg/initialization.jl b/src/algorithms/ctmrg/initialization.jl index c44f04826..90dc7470a 100644 --- a/src/algorithms/ctmrg/initialization.jl +++ b/src/algorithms/ctmrg/initialization.jl @@ -50,7 +50,7 @@ _check_two_layer(::InfiniteSquareNetwork) = false _check_two_layer(::InfiniteSquareNetwork{<:PEPSSandwich}) = true """ - initialize_ctmrg_environment([elt::Type{<:Number},] n::InfiniteSquareNetwork, alg::RandomInitialization, [env0]) + initialize_ctmrg_environment([elt::Type,] n::InfiniteSquareNetwork, alg::RandomInitialization, [env0]) Initialize a `CTMRGEnv` corresponding to a product state acting as an identity between the virtual spaces of a two-layer network, for example @@ -83,7 +83,7 @@ function initialize_ctmrg_environment( return initialize_ctmrg_environment(scalartype(A), A, args...; kwargs...) end function initialize_ctmrg_environment( - elt::Type{<:Number}, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; + elt::Type, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; kwargs... ) return initialize_ctmrg_environment(similarstoragetype(storagetype(A), elt), InfiniteSquareNetwork(A), args...; kwargs...) diff --git a/src/environments/bp_environments.jl b/src/environments/bp_environments.jl index 85efd256d..afc2856f9 100644 --- a/src/environments/bp_environments.jl +++ b/src/environments/bp_environments.jl @@ -108,7 +108,7 @@ function BPEnv( f, T, D_north::P, D_east::P; unitcell::Tuple{Int, Int} = (1, 1), posdef::Bool = true ) where {P <: ProductSpace} - return BPEnv(f, T, N, _fill_edge_physical_spaces(D_north, D_east; unitcell)...; posdef) + return BPEnv(f, T, _fill_edge_physical_spaces(D_north, D_east; unitcell)...; posdef) end """ diff --git a/src/environments/suweight.jl b/src/environments/suweight.jl index a508cf070..796c4e711 100644 --- a/src/environments/suweight.jl +++ b/src/environments/suweight.jl @@ -58,7 +58,7 @@ function SUWeight(wts_mats::AbstractMatrix{E}...) where {E <: PEPSWeight} end """ - SUWeight(T, Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:ElementarySpace}} + SUWeight([T = ComplexF64,] Nspaces::M, [Espaces::M]) where {M<:AbstractMatrix{<:ElementarySpace}} Create a trivial `SUWeight` by specifying the vertical (north) or horizontal (east) virtual bond spaces. `T` is either a scalar type (like `ComplexF32`) or an array type (like `Vector{Float64}`) that @@ -72,13 +72,15 @@ function SUWeight( Nr, Nc = size(Nspaces) weights = map(Iterators.product(1:2, 1:Nr, 1:Nc)) do (d, r, c) V = (d == 1 ? Espaces[r, c] : Nspaces[r, c]) - realT = similarstoragetype(T, real(eltype(T))) + realT = similarstoragetype(similarstoragetype(T), real(eltype(T))) diag = realT(undef, reduceddim(V)) fill!(diag, one(real(eltype(T)))) DiagonalTensorMap(diag, V) end return SUWeight(weights) end +SUWeight(Nspaces::M, Espaces::M = Nspaces) where {M <: AbstractMatrix{<:ElementarySpace}} = + SUWeight(ComplexF64, Nspaces, Espaces) """ SUWeight(T, Nspace::S, Espace::S=Nspace; unitcell::Tuple{Int,Int}=(1, 1)) where {S<:ElementarySpace} diff --git a/src/operators/transfermatrix.jl b/src/operators/transfermatrix.jl index 7280a9dfc..fd94825e1 100644 --- a/src/operators/transfermatrix.jl +++ b/src/operators/transfermatrix.jl @@ -144,7 +144,7 @@ virtualspace(O::InfiniteTransferMatrix, i, dir) = virtualspace(O[i], dir) Inialize a boundary MPS for the transfer operator `O` by specifying an array of virtual spaces consistent with the unit cell. """ -function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix}, arg; kwargs...) # initialize(f=randn, T=scalartype(O), O, ...) +function initialize_mps(O::Union{InfiniteTransferMatrix, MultilineTransferMatrix}, arg; kwargs...) # initialize(f=randn, T=storagetype(O), O, ...) return initialize_mps(randn, storagetype(O), O, arg; kwargs...) end function initialize_mps( diff --git a/src/states/infinitepeps.jl b/src/states/infinitepeps.jl index d650b3e09..d077f23e8 100644 --- a/src/states/infinitepeps.jl +++ b/src/states/infinitepeps.jl @@ -46,7 +46,7 @@ Create an `InfinitePEPS` by specifying the physical, north virtual and east virt of the PEPS tensor at each site in the unit cell as a matrix. """ function InfinitePEPS( - f, T, Pspaces::M, Nspaces::M, Espaces::M = Nspaces + f, T::Type, Pspaces::M, Nspaces::M, Espaces::M = Nspaces ) where {M <: AbstractMatrix{<:ElementarySpace}} size(Pspaces) == size(Nspaces) == size(Espaces) || throw(ArgumentError("Input spaces should have equal sizes.")) @@ -108,8 +108,8 @@ end Create an InfinitePEPS by specifying its physical, north and east spaces and unit cell. """ function InfinitePEPS( - f, ::Type{T}, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) - ) where {T <: Union{Number, AbstractArray{<:Number}}, S <: ElementarySpace} + f, T::Type, Pspace::S, vspaces...; unitcell::Tuple{Int, Int} = (1, 1) + ) where {S <: ElementarySpace} return InfinitePEPS( f, T, _fill_state_physical_spaces(Pspace; unitcell), From c005f16265a327c98f88ed5bf00ccdb4808197d9 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 15 Oct 2026 09:30:52 -0400 Subject: [PATCH 8/9] Handle initing ctmrg envs with both numbers and arrays --- src/algorithms/ctmrg/initialization.jl | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/algorithms/ctmrg/initialization.jl b/src/algorithms/ctmrg/initialization.jl index 90dc7470a..5b44c7a69 100644 --- a/src/algorithms/ctmrg/initialization.jl +++ b/src/algorithms/ctmrg/initialization.jl @@ -1,5 +1,5 @@ """ - initialize_ctmrg_environment([elt::Type{<:Number},] n::InfiniteSquareNetwork, alg::RandomInitialization, virtual_spaces...) + initialize_ctmrg_environment([elt::Type,] n::InfiniteSquareNetwork, alg::RandomInitialization, virtual_spaces...) Initialize a fully random `CTMRGEnv` using the given environment virtual spaces. See [`CTMRGEnv`](@ref) for details on the expected format of the virtual spaces. @@ -14,7 +14,7 @@ function initialize_ctmrg_environment( end """ - initialize_ctmrg_environment([elt::Type{<:Number},] n::InfiniteSquareNetwork, alg::RandomInitialization) + initialize_ctmrg_environment([elt::Type,] n::InfiniteSquareNetwork, alg::RandomInitialization) Initialize a `CTMRGEnv` corresponding to a product state with trivial virtual spaces and corners. The product state edge tensors are initialized as `alg.f(elt, V::ProductSpace)`. @@ -29,7 +29,7 @@ function initialize_ctmrg_environment( end """ - initialize_ctmrg_environment([elt::Type{<:Number},] n::InfiniteSquareNetwork, alg::RandomInitialization, [env0]) + initialize_ctmrg_environment([elt::Type,] n::InfiniteSquareNetwork, alg::RandomInitialization, [env0]) Initialize a `CTMRGEnv` by applying a single untruncated iteration of [`SimultaneousCTMRG`](@ref) to a given initial environment. By default, the starting @@ -83,8 +83,15 @@ function initialize_ctmrg_environment( return initialize_ctmrg_environment(scalartype(A), A, args...; kwargs...) end function initialize_ctmrg_environment( - elt::Type, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; + elt::Type{<:Number}, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; kwargs... ) return initialize_ctmrg_environment(similarstoragetype(storagetype(A), elt), InfiniteSquareNetwork(A), args...; kwargs...) end + +function initialize_ctmrg_environment( + elt::Type{<:AbstractArray}, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; + kwargs... + ) + return initialize_ctmrg_environment(similarstoragetype(elt, scalartype(A)), InfiniteSquareNetwork(A), args...; kwargs...) +end From 67938374d341354a79bcba630f0b3b6aa72369c9 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 15 Oct 2026 09:43:49 -0400 Subject: [PATCH 9/9] Kill extraneous method --- src/algorithms/ctmrg/initialization.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/algorithms/ctmrg/initialization.jl b/src/algorithms/ctmrg/initialization.jl index 5b44c7a69..42d7a6d87 100644 --- a/src/algorithms/ctmrg/initialization.jl +++ b/src/algorithms/ctmrg/initialization.jl @@ -88,10 +88,3 @@ function initialize_ctmrg_environment( ) return initialize_ctmrg_environment(similarstoragetype(storagetype(A), elt), InfiniteSquareNetwork(A), args...; kwargs...) end - -function initialize_ctmrg_environment( - elt::Type{<:AbstractArray}, A::Union{InfinitePEPS, InfinitePartitionFunction}, args...; - kwargs... - ) - return initialize_ctmrg_environment(similarstoragetype(elt, scalartype(A)), InfiniteSquareNetwork(A), args...; kwargs...) -end