Skip to content

Commit a405825

Browse files
committed
Fix issue: to_wn() suffers from loss of accuracy if R is large
1 parent ae5e43d commit a405825

File tree

5 files changed

+88
-13
lines changed

5 files changed

+88
-13
lines changed

Project.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3838
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
3939
ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823"
4040
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
41+
TensorCrossInterpolation = "b261b2ec-6378-4871-b32e-9173bb050604"
42+
QuanticsTCI = "b11687fd-3a1c-4c41-97d0-998ab401d50e"
43+
QuanticsGrids = "634c7f73-3e90-4749-a1bd-001b8efc642d"
44+
SparseIR = "4fe2279e-80f0-4adb-8463-ee114ff56b7d"
4145

4246
[targets]
43-
test = ["Test", "Random", "ReTestItems", "Aqua", "PartitionedMPSs"]
47+
test = ["Test", "Random", "ReTestItems", "Aqua", "PartitionedMPSs", "TensorCrossInterpolation", "QuanticsTCI", "QuanticsGrids", "SparseIR"]

src/fouriertransform.jl

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ We denote the input and output MPS's by ``X`` and ``Y``, respectively.
1919
* ``Y(y_N, ..., y_1) = Y_1(y_N) ... Y_N (y_1)``.
2020
2121
"""
22-
function _qft(sites; cutoff::Float64=1e-14, sign::Int=1)
22+
function _qft(sites; cutoff::Float64=1e-25, sign::Int=1)
2323
if !all(dim.(sites) .== 2)
2424
error("All siteinds for qft must has Qubit tag")
2525
end
@@ -108,8 +108,8 @@ function fouriertransform(M::MPS;
108108
tag::String="",
109109
sitessrc=nothing,
110110
sitesdst=nothing,
111-
originsrc::Float64=0.0,
112-
origindst::Float64=0.0,
111+
originsrc::Real=0.0,
112+
origindst::Real=0.0,
113113
cutoff_MPO=1e-25, kwargs...)
114114
sites = siteinds(M)
115115
sitepos, target_sites = _find_target_sites(M; sitessrc=sitessrc, tag=tag)
@@ -122,12 +122,15 @@ function fouriertransform(M::MPS;
122122
error("Invalid target_sites")
123123
end
124124

125+
p_back = precision(BigFloat)
126+
setprecision(BigFloat, 256)
127+
125128
# Prepare MPO for QFT
126129
MQ_ = _qft(target_sites; sign=sign, cutoff=cutoff_MPO)
127130
MQ = matchsiteinds(MQ_, sites)
128131

129132
# Phase shift from origindst
130-
M_result = phase_rotation(M, sign * 2π * origindst / (2.0^length(sitepos));
133+
M_result = phase_rotation(M, sign * 2π * BigFloat(origindst) / (BigFloat(2)^length(sitepos));
131134
targetsites=target_sites, kwargs...)
132135

133136
# Apply QFT
@@ -139,10 +142,13 @@ function fouriertransform(M::MPS;
139142
end
140143

141144
# Phase shift from originsrc
142-
M_result = phase_rotation(M_result, sign * 2π * originsrc / (2.0^length(sitepos));
145+
M_result = phase_rotation(M_result, sign * 2π * BigFloat(originsrc) / (BigFloat(2)^length(sitepos));
143146
targetsites=sitesdst, kwargs...)
144147

145-
M_result *= exp(sign * im * 2π * originsrc * origindst / 2.0^length(sitepos))
148+
tmp = Float64(mod(sign * 2π * BigFloat(originsrc) * BigFloat(origindst) / BigFloat(2)^length(sitepos), 2 * π))
149+
M_result *= exp(im * tmp)
150+
151+
setprecision(BigFloat, p_back)
146152

147153
return M_result
148154
end

src/imaginarytime.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,27 @@ function to_wn(stat::Statistics, gtau::MPS, beta::Float64; sitessrc=nothing, tag
2020
sitesdst=nothing, kwargs...)::MPS
2121
sitepos, _ = _find_target_sites(gtau; sitessrc=sitessrc, tag=tag)
2222
nqbit_t = length(sitepos)
23-
originwn = 0.5 * (-2.0^nqbit_t + _stat_shift(stat))
23+
p_back = precision(BigFloat)
24+
setprecision(BigFloat, 256)
25+
originwn = 0.5 * (-BigFloat(2)^BigFloat(nqbit_t) + _stat_shift(stat))
2426
giv = fouriertransform(gtau; tag=tag, sitessrc=sitessrc, sitesdst=sitesdst,
2527
origindst=originwn, kwargs...)
2628
giv *= (beta * 2^(-nqbit_t / 2))
29+
setprecision(BigFloat, p_back)
2730
return giv
2831
end
2932

3033
function to_tau(stat::Statistics, giv::MPS, beta::Float64; sitessrc=nothing, tag="",
3134
sitesdst=nothing, kwargs...)::MPS
3235
sitepos, _ = _find_target_sites(giv; sitessrc=sitessrc, tag=tag)
36+
p_back = precision(BigFloat)
37+
setprecision(BigFloat, 256)
3338
nqbit_t = length(sitepos)
34-
originwn = 0.5 * (-2.0^nqbit_t + _stat_shift(stat))
39+
originwn = 0.5 * (-BigFloat(2)^BigFloat(nqbit_t) + _stat_shift(stat))
3540
gtau = fouriertransform(giv; sign=-1, tag=tag, sitessrc=sitessrc, sitesdst=sitesdst,
3641
originsrc=originwn, kwargs...)
3742
gtau *= ((2^(nqbit_t / 2)) / beta)
43+
setprecision(BigFloat, p_back)
3844
return gtau
3945
end
4046

src/transformer.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ end
116116
"""
117117
Multiply by exp(i θ x), where x = (x_1, ..., x_R)_2.
118118
"""
119-
function phase_rotation(M::MPS, θ::Float64; targetsites=nothing, tag="", kwargs...)::MPS
119+
function phase_rotation(M::MPS, θ::Real; targetsites=nothing, tag="", kwargs...)::MPS
120120
transformer = phase_rotation_mpo(siteinds(M), θ; targetsites=targetsites, tag=tag)
121121
_apply(transformer, M; kwargs...)
122122
end
@@ -126,18 +126,22 @@ Create an MPO for multiplication by `exp(i θ x)`, where `x = (x_1, ..., x_R)_2`
126126
127127
`sites`: site indices for `x_1`, `x_2`, ..., `x_R`.
128128
"""
129-
function phase_rotation_mpo(sites::AbstractVector{Index{T}}, θ::Float64;
129+
function phase_rotation_mpo(sites::AbstractVector{Index{T}}, θ::Real;
130130
targetsites=nothing, tag="")::MPO where {T}
131131
_, target_sites = _find_target_sites(sites; sitessrc=targetsites, tag=tag)
132132
transformer = _phase_rotation_mpo(target_sites, θ)
133133
return matchsiteinds(transformer, sites)
134134
end
135135

136-
function _phase_rotation_mpo(sites::AbstractVector{Index{T}}, θ::Float64)::MPO where {T}
136+
function _phase_rotation_mpo(sites::AbstractVector{Index{T}}, θ::Real)::MPO where {T}
137137
R = length(sites)
138138
tensors = [ITensor(true) for _ in 1:R]
139+
θ_mod = mod(θ, 2π)
140+
p_back = precision(BigFloat)
141+
setprecision(BigFloat, 256)
139142
for n in 1:R
140-
tensors[n] = ITensors.SiteTypes.op("Phase", sites[n]; ϕ=θ * 2^(R - n))
143+
tmp = Float64(mod(θ_mod * BigFloat(2)^BigFloat(R - n), 2 * π))
144+
tensors[n] = ITensors.SiteTypes.op("Phase", sites[n]; ϕ=tmp)
141145
end
142146
links = [Index(1, "Link,l=$l") for l in 1:(R - 1)]
143147
tensors[1] = ITensor(
@@ -149,6 +153,7 @@ function _phase_rotation_mpo(sites::AbstractVector{Index{T}}, θ::Float64)::MPO
149153
tensors[end] = ITensor(
150154
Array(tensors[end], sites[end]', sites[end]), links[end], sites[end], sites[end]')
151155

156+
setprecision(BigFloat, p_back)
152157
return MPO(tensors)
153158
end
154159

test/imaginarytime_tests.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
@testitem "imaginarytime_tests.jl/imaginarytime" begin
22
using Test
33
using Quantics
4+
import Quantics
45
using ITensors: siteinds, Index
56
using ITensors.SiteTypes: op
67
import ITensors
78
import SparseIR: Fermionic, Bosonic, FermionicFreq, valueim
89

10+
import ITensorMPS: MPS, onehot
11+
import QuanticsGrids as QG
12+
import TensorCrossInterpolation as TCI
13+
import QuanticsTCI: quanticscrossinterpolate
14+
import TCIITensorConversion
15+
916
function _test_data_imaginarytime(nbit, β)
1017
ω = 0.5
1118
N = 2^nbit
@@ -80,6 +87,52 @@
8087
@test maximum(abs, (gtau - gtau_smpl)[trunc(Int, 0.2 * nτ):trunc(Int, 0.8 * nτ)]) <
8188
1e-2
8289
end
90+
91+
92+
@testset "ImaginaryTimeFT.to_tau with large R" begin
93+
function fermionic_wn(n, β)
94+
return (2 * n + 1) * π / β
95+
end
96+
97+
function inv_iwn(n, β; ϵ=0.0)
98+
return 1.0 / (im * fermionic_wn(n, β) - ϵ)
99+
end
100+
101+
_evaluate::MPS, sites, index::Vector{Int}) = only(reduce(
102+
*, Ψ[n] * onehot(sites[n] => index[n]) for n in 1:length(Ψ)))
103+
104+
β = 100.0
105+
R = 50
106+
N = 2^R
107+
N_half = 2^(R - 1)
108+
tol = 1e-16
109+
maxdim_TCI = 100
110+
maxdim_contract = 1000
111+
cutoff_mpo = 1e-30
112+
cutoff_contract = 1e-30
113+
τ_check = 0.99 * β
114+
115+
ngrid = QG.InherentDiscreteGrid{1}(R, -N_half)
116+
τgrid = QG.DiscretizedGrid{1}(R, 0, β)
117+
118+
sitesiω = [Index(2, "Qubit, iω=$n") for n in 1:R]
119+
sitesτ = [Index(2, "Qubit, τ=$n") for n in 1:R]
120+
121+
inv_iwn_tci(n) = inv_iwn(n, β; ϵ= 0.0)
122+
qtci2, ranks2, errors2 = quanticscrossinterpolate(
123+
ComplexF64, inv_iwn_tci, ngrid; tolerance=tol, maxbonddim=maxdim_TCI)
124+
125+
inv_iwn_tt = TCI.TensorTrain(qtci2.tci)
126+
iwmps = MPS(inv_iwn_tt; sites=sitesiω)
127+
128+
fourier_inv_iw = Quantics.to_tau(
129+
Fermionic(), iwmps, β; tag="", sitesdst=sitesτ, cutoff_MPO=cutoff_mpo,
130+
cutoff=cutoff_contract, maxdim=maxdim_contract, alg="naive")
131+
132+
gtau_reconst = _evaluate(fourier_inv_iw, reverse(sitesτ), reverse(QG.origcoord_to_quantics(τgrid, τ_check)))
133+
134+
@test abs(gtau_reconst - (-1/2)) < 1e-11
135+
end
83136
end
84137

85138
@testitem "imaginarytime_tests.jl/poletomps" begin
@@ -112,4 +165,5 @@ end
112165
gtauref = gtauf.(LinRange(0, β, 2^nqubit + 1)[1:(end - 1)])
113166
@test maximum(abs, gtauref .- gtauvec) < 1e-14
114167
end
168+
115169
end

0 commit comments

Comments
 (0)