Skip to content

Commit 04d004b

Browse files
committed
Add a Sobol sequence wrapper that includes the initial point (0, 0, ...)
C.f. JuliaMath/Sobol.jl#31
1 parent 7e2bc08 commit 04d004b

File tree

6 files changed

+55
-32
lines changed

6 files changed

+55
-32
lines changed

src/inchworm.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ module inchworm
22

33
using Printf
44

5-
import Sobol: SobolSeq
6-
75
import Keldysh; kd = Keldysh
86

97
import QInchworm; teval = QInchworm.topology_eval
108

9+
using QInchworm.utility: BetterSobolSeq, next!
10+
1111
import QInchworm.configuration: Expansion,
1212
Configurations,
1313
operator,
@@ -81,7 +81,7 @@ function inchworm_step(expansion::Expansion,
8181

8282
teval.update_inch_times!(od.configurations, t_i, t_w, t_f)
8383

84-
seq = SobolSeq(2 * od.order)
84+
seq = BetterSobolSeq(2 * od.order)
8585
N = 0
8686
order_contrib = deepcopy(zero_sector_block_matrix)
8787
order_contrib_prev = deepcopy(zero_sector_block_matrix)
@@ -156,7 +156,7 @@ function inchworm_step_bare(expansion::Expansion,
156156
teval.update_inch_times!(od.configurations, t_i, t_i, t_f)
157157

158158
d = 2 * od.order
159-
seq = SobolSeq(d)
159+
seq = BetterSobolSeq(d)
160160
N = 0
161161
order_contrib = deepcopy(zero_sector_block_matrix)
162162
order_contrib_prev = deepcopy(zero_sector_block_matrix)

src/qmc_integrate.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
module qmc_integrate
22

3-
import Sobol: SobolSeq, next!
43
import Keldysh; kd = Keldysh
54

6-
import QInchworm.utility: get_ref
5+
using QInchworm.utility: get_ref, BetterSobolSeq, next!
76

87
#
98
# I use the notations introduced in https://arxiv.org/pdf/2002.12372.pdf.
@@ -170,7 +169,7 @@ function qmc_time_ordered_integral(f,
170169
t_i::kd.BranchPoint,
171170
t_f::kd.BranchPoint;
172171
init = zero(contour_function_return_type(f)),
173-
seq = SobolSeq(d),
172+
seq = BetterSobolSeq(d),
174173
τ::Real,
175174
N::Int)
176175
@assert kd.heaviside(c, t_f, t_i)
@@ -225,7 +224,7 @@ function qmc_time_ordered_integral_n_samples(
225224
t_i::kd.BranchPoint,
226225
t_f::kd.BranchPoint;
227226
init = zero(contour_function_return_type(f)),
228-
seq = SobolSeq(d),
227+
seq = BetterSobolSeq(d),
229228
τ::Real,
230229
N_samples::Int)
231230
@assert kd.heaviside(c, t_f, t_i)
@@ -276,7 +275,7 @@ function qmc_time_ordered_integral_sort(f,
276275
t_i::kd.BranchPoint,
277276
t_f::kd.BranchPoint;
278277
init = zero(contour_function_return_type(f)),
279-
seq = SobolSeq(d),
278+
seq = BetterSobolSeq(d),
280279
N::Int)
281280
@assert kd.heaviside(c, t_f, t_i)
282281

@@ -321,7 +320,7 @@ function qmc_time_ordered_integral_root(f,
321320
t_i::kd.BranchPoint,
322321
t_f::kd.BranchPoint;
323322
init = zero(contour_function_return_type(f)),
324-
seq = SobolSeq(d),
323+
seq = BetterSobolSeq(d),
325324
N::Int)
326325
@assert kd.heaviside(c, t_f, t_i)
327326

@@ -394,7 +393,7 @@ function qmc_inchworm_integral_root(f,
394393
t_w::kd.BranchPoint,
395394
t_f::kd.BranchPoint;
396395
init = zero(contour_function_return_type(f)),
397-
seq = SobolSeq(d_bold + d_bare),
396+
seq = BetterSobolSeq(d_bold + d_bare),
398397
N::Int)
399398
@assert kd.heaviside(c, t_w, t_i)
400399
@assert kd.heaviside(c, t_f, t_w)

src/utility.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ using Interpolations: BoundaryCondition,
99
WoodburyMatrices,
1010
lut!
1111

12+
import Sobol: AbstractSobolSeq, SobolSeq, next!, ndims
13+
1214
"""
1315
Inverse of get_point(c::AbstractContour, ref)
1416
@@ -92,4 +94,25 @@ function (spline::IncrementalSpline{T})(z) where {T<:Number}
9294
@inbounds spline.data[i] * (1-δx^2) + spline.data[i + 1] * (1-(1-δx)^2) + c3 * (0.25-(δx-0.5)^2)
9395
end
9496

97+
"""
98+
Sobol sequence including the initial point (0, 0, ...)
99+
100+
C.f. https://github.com/stevengj/Sobol.jl/issues/31
101+
"""
102+
mutable struct BetterSobolSeq{N} <: AbstractSobolSeq{N}
103+
seq::SobolSeq{N}
104+
init_pt_returned::Bool
105+
106+
BetterSobolSeq(N::Int) = new{N}(SobolSeq(N), false)
107+
end
108+
109+
function next!(bseq::BetterSobolSeq)
110+
if bseq.init_pt_returned
111+
next!(bseq.seq)
112+
else
113+
bseq.init_pt_returned = true
114+
zeros(Float64, ndims(bseq.seq))
115+
end
116+
end
117+
95118
end

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[deps]
2+
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
23
Keldysh = "50f2bc7e-5fd7-11e9-13c7-85fb88b4f34f"
34
KeldyshED = "675b6b9c-7c2f-11e9-3bf3-dfd4d61640f7"
45
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

test/nca_equil.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ end
4646
tmax = 1.
4747

4848
# -- Quasi Monte Carlo
49-
N = 10000
49+
N = 2^13
5050

5151
# -- Exact Diagonalization
5252

test/qmc_integrate.jl

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
2121
τ = 5.0
2222

2323
@testset "d = 1, constant integrand" begin
24-
let d = 1, c = contour, f = t -> 1.0, N = 200000
24+
let d = 1, c = contour, f = t -> 1.0, N = 2^17
2525
val, N_samples = qmc_time_ordered_integral(f, d, c, c(0.1), c(0.5); τ=τ, N=N)
2626
@show N_samples / N
2727
@test isapprox(val, -0.4, rtol=1e-4)
@@ -41,7 +41,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
4141
end
4242

4343
@testset "d = 1, linear in t integrand" begin
44-
let d = 1, c = contour, f = t -> t[1].val, N = 200000
44+
let d = 1, c = contour, f = t -> t[1].val, N = 2^17
4545
val, N_samples = qmc_time_ordered_integral(f, d, c, c(0.1), c(0.5), τ=τ, N=N)
4646
@show N_samples / N
4747
@test isapprox(val, -0.28, rtol=1e-4)
@@ -61,7 +61,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
6161
end
6262

6363
@testset "d = 2, constant integrand" begin
64-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 500000
64+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 2^18
6565
val, N_samples = qmc_time_ordered_integral(f, d, c, c(0.1), c(0.5), τ=τ, N=N)
6666
@show N_samples / N
6767
@test isapprox(val, 0.08, rtol=5e-3)
@@ -81,7 +81,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
8181
end
8282

8383
@testset "d = 2, bilinear in t1, t2 integrand" begin
84-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 1000000
84+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 2^19
8585
val, N_samples = qmc_time_ordered_integral(f, d, c, c(0.1), c(0.5), τ=τ, N=N)
8686
@show N_samples / N
8787
@test isapprox(val, 0.0392, rtol=5e-3)
@@ -106,7 +106,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
106106
τ = 5.0
107107

108108
@testset "d = 1, constant integrand" begin
109-
let d = 1, c = contour, f = t -> 1.0, N_samples = 50000
109+
let d = 1, c = contour, f = t -> 1.0, N_samples = 2^16
110110
val, N = qmc_time_ordered_integral_n_samples(f, d, c, c(0.1), c(0.5); τ=τ, N_samples=N_samples)
111111
@show N_samples / N
112112
@test isapprox(val, -0.4, rtol=1e-4)
@@ -126,7 +126,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
126126
end
127127

128128
@testset "d = 1, linear in t integrand" begin
129-
let d = 1, c = contour, f = t -> t[1].val, N_samples = 50000
129+
let d = 1, c = contour, f = t -> t[1].val, N_samples = 2^15
130130
val, N = qmc_time_ordered_integral_n_samples(f, d, c, c(0.1), c(0.5), τ=τ, N_samples=N_samples)
131131
@show N_samples / N
132132
@test isapprox(val, -0.28, rtol=1e-4)
@@ -146,7 +146,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
146146
end
147147

148148
@testset "d = 2, constant integrand" begin
149-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N_samples = 50000
149+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N_samples = 2^15
150150
val, N = qmc_time_ordered_integral_n_samples(f, d, c, c(0.1), c(0.5), τ=τ, N_samples=N_samples)
151151
@show N_samples / N
152152
@test isapprox(val, 0.08, rtol=5e-3)
@@ -166,7 +166,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
166166
end
167167

168168
@testset "d = 2, bilinear in t1, t2 integrand" begin
169-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N_samples = 50000
169+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N_samples = 2^15
170170
val, N = qmc_time_ordered_integral_n_samples(f, d, c, c(0.1), c(0.5), τ=τ, N_samples=N_samples)
171171
@show N_samples / N
172172
@test isapprox(val, 0.0392, rtol=5e-3)
@@ -189,7 +189,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
189189
@testset "qmc_time_ordered_integral_sort()" begin
190190

191191
@testset "d = 1, constant integrand" begin
192-
let d = 1, c = contour, f = t -> 1.0, N = 200000
192+
let d = 1, c = contour, f = t -> 1.0, N = 2^17
193193
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(0.5); N=N)
194194
@test isapprox(val, -0.4, rtol=1e-4)
195195
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(2.0); N=N)
@@ -204,7 +204,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
204204
end
205205

206206
@testset "d = 1, linear in t integrand" begin
207-
let d = 1, c = contour, f = t -> t[1].val, N = 200000
207+
let d = 1, c = contour, f = t -> t[1].val, N = 2^18
208208
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(0.5), N=N)
209209
@test isapprox(val, -0.28, rtol=1e-5)
210210
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(2.0), N=N)
@@ -219,7 +219,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
219219
end
220220

221221
@testset "d = 2, constant integrand" begin
222-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 500000
222+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 2^18
223223
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(0.5), N=N)
224224
@test isapprox(val, 0.08, rtol=1e-4)
225225
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(2.0), N=N)
@@ -234,7 +234,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
234234
end
235235

236236
@testset "d = 2, bilinear in t1, t2 integrand" begin
237-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 1000000
237+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 2^19
238238
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(0.5), N=N)
239239
@test isapprox(val, 0.0392, rtol=1e-4)
240240
val = qmc_time_ordered_integral_sort(f, d, c, c(0.1), c(2.0), N=N)
@@ -252,7 +252,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
252252
@testset "qmc_time_ordered_integral_root()" begin
253253

254254
@testset "d = 1, constant integrand" begin
255-
let d = 1, c = contour, f = t -> 1.0, N = 200000
255+
let d = 1, c = contour, f = t -> 1.0, N = 2^17
256256
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(0.5); N=N)
257257
@test isapprox(val, -0.4, rtol=1e-4)
258258
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(2.0); N=N)
@@ -267,7 +267,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
267267
end
268268

269269
@testset "d = 1, linear in t integrand" begin
270-
let d = 1, c = contour, f = t -> t[1].val, N = 200000
270+
let d = 1, c = contour, f = t -> t[1].val, N = 2^18
271271
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(0.5), N=N)
272272
@test isapprox(val, -0.28, rtol=1e-5)
273273
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(2.0), N=N)
@@ -282,7 +282,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
282282
end
283283

284284
@testset "d = 2, constant integrand" begin
285-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 500000
285+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); 1.0), N = 2^18
286286
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(0.5), N=N)
287287
@test isapprox(val, 0.08, rtol=1e-4)
288288
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(2.0), N=N)
@@ -297,7 +297,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
297297
end
298298

299299
@testset "d = 2, bilinear in t1, t2 integrand" begin
300-
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 1000000
300+
let d = 2, c = contour, f = t -> (@assert kd.heaviside(c, t[1], t[2]); t[1].val * t[2].val), N = 2^19
301301
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(0.5), N=N)
302302
@test isapprox(val, 0.0392, rtol=1e-4)
303303
val = qmc_time_ordered_integral_root(f, d, c, c(0.1), c(2.0), N=N)
@@ -315,7 +315,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
315315
@testset "qmc_inchworm_integral_root()" begin
316316

317317
@testset "d_bold = 0, d_bare = 3, constant integrand" begin
318-
let d_bold = 0, d_bare = 3, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 1000000
318+
let d_bold = 0, d_bare = 3, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2^19
319319
function f(t)
320320
@assert kd.heaviside(c, t_f, t[1])
321321
@assert kd.heaviside(c, t[1], t[2])
@@ -329,7 +329,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
329329
end
330330

331331
@testset "d_bold = 0, d_bare = 3, multilinear integrand" begin
332-
let d_bold = 0, d_bare = 3, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 1000000
332+
let d_bold = 0, d_bare = 3, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2^19
333333
function f(t)
334334
@assert kd.heaviside(c, t_f, t[1])
335335
@assert kd.heaviside(c, t[1], t[2])
@@ -343,7 +343,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
343343
end
344344

345345
@testset "d_bold = 3, d_bare = 2, constant integrand" begin
346-
let d_bold = 3, d_bare = 2, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2000000
346+
let d_bold = 3, d_bare = 2, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2^20
347347
function f(t)
348348
@assert kd.heaviside(c, t_f, t[1])
349349
@assert kd.heaviside(c, t[1], t[2])
@@ -360,7 +360,7 @@ import QInchworm.qmc_integrate: qmc_time_ordered_integral,
360360
end
361361

362362
@testset "d_bold = 3, d_bare = 2, multilinear integrand" begin
363-
let d_bold = 3, d_bare = 2, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2000000
363+
let d_bold = 3, d_bare = 2, c = contour, t_i = c(1.1), t_w = c(5.0), t_f = c(5.5), N = 2^20
364364
function f(t)
365365
@assert kd.heaviside(c, t_f, t[1])
366366
@assert kd.heaviside(c, t[1], t[2])

0 commit comments

Comments
 (0)