• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wexlergroup / FreeBird.jl / 17626155224

10 Sep 2025 08:34PM UTC coverage: 95.369% (-0.2%) from 95.543%
17626155224

push

github

web-flow
Merge pull request #112 from wexlergroup/hotfix/remove-swap-chemsymbols

Deleted the line that swapped the chemical symbol.

1668 of 1749 relevant lines covered (95.37%)

73253.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.34
/src/SamplingSchemes/nested_sampling.jl
1
"""
2
    mutable struct NestedSamplingParameters <: SamplingParameters
3

4
The `NestedSamplingParameters` struct represents the parameters used in the nested sampling scheme.
5

6
# Fields
7
- `mc_steps::Int64`: The number of total Monte Carlo moves to perform.
8
- `initial_step_size::Float64`: The initial step size, which is the fallback step size if MC routine fails to accept a move.
9
- `step_size::Float64`: The on-the-fly step size used in the sampling process.
10
- `step_size_lo::Float64`: The lower bound of the step size.
11
- `step_size_up::Float64`: The upper bound of the step size.
12
- `accept_range::Tuple{Float64, Float64}`: The range of acceptance rates for adjusting the step size.
13
e.g. (0.25, 0.75) means that the step size will decrease if the acceptance rate is below 0.25 and increase if it is above 0.75.
14
- `fail_count::Int64`: The number of failed MC moves in a row.
15
- `allowed_fail_count::Int64`: The maximum number of failed MC moves allowed before resetting the step size.
16
- `energy_perturbation::Float64`: The perturbation value used to adjust the energy of the walkers.
17
- `random_seed::Int64`: The seed for the random number generator.
18
"""
19
mutable struct NestedSamplingParameters <: SamplingParameters
20
    mc_steps::Int64
36✔
21
    initial_step_size::Float64
22
    step_size::Float64
23
    step_size_lo::Float64
24
    step_size_up::Float64
25
    accept_range::Tuple{Float64, Float64}
26
    fail_count::Int64
27
    allowed_fail_count::Int64
28
    energy_perturbation::Float64
29
    random_seed::Int64
30
end
31

32
function NestedSamplingParameters(;
35✔
33
            mc_steps::Int64=200,
34
            initial_step_size::Float64=0.01,
35
            step_size::Float64=0.1,
36
            step_size_lo::Float64=1e-6,
37
            step_size_up::Float64=1.0,
38
            accept_range::Tuple{Float64, Float64}=(0.25, 0.75),
39
            fail_count::Int64=0,
40
            allowed_fail_count::Int64=100,
41
            energy_perturbation::Float64=1e-12,
42
            random_seed::Int64=1234,
43
            )
44
    NestedSamplingParameters(mc_steps, initial_step_size, step_size, step_size_lo, step_size_up, accept_range, fail_count, allowed_fail_count, energy_perturbation, random_seed)  
20✔
45
end
46

47
"""
48
    LatticeNestedSamplingParameters(;
49
            mc_steps::Int64=100,
50
            energy_perturbation::Float64=1e-12,
51
            fail_count::Int64=0,
52
            allowed_fail_count::Int64=10,
53
            random_seed::Int64=1234,
54
            )
55
A convenience constructor for `NestedSamplingParameters` with default values suitable for lattice systems.
56
"""
57
function LatticeNestedSamplingParameters(;
28✔
58
            mc_steps::Int64=100,
59
            energy_perturbation::Float64=1e-12,
60
            fail_count::Int64=0,
61
            allowed_fail_count::Int64=10,
62
            random_seed::Int64=1234,
63
            )
64
    NestedSamplingParameters(mc_steps=mc_steps, fail_count=fail_count, allowed_fail_count=allowed_fail_count, energy_perturbation=energy_perturbation, random_seed=random_seed)
16✔
65
end
66

67

68
"""
69
    abstract type MCRoutine
70

71
An abstract type representing a Monte Carlo routine.
72

73
Currently, the following concrete types are supported:
74
- `MCRandomWalkMaxE`: A type for generating a new walker by performing a random walk for decorrelation on the
75
highest-energy walker.
76
- `MCRandomWalkClone`: A type for generating a new walker by cloning an existing walker and performing a random walk
77
for decorrelation.
78
- `MCNewSample`: A type for generating a new walker from a random configuration. Currently, it is intended to use 
79
this routine for lattice gas systems.
80
- `MCMixedMoves`: A type for generating a new walker by performing random walks and swapping atoms. Currently, it is
81
intended to use this routine for multi-component systems. The actual number of random walks and swaps to perform is
82
determined by the weights of the fields `walks_freq` and `swaps_freq`. See [`MCMixedMoves`](@ref).
83
- `MCRejectionSampling`: A type for generating a new walker by performing rejection sampling. Currently, it is intended
84
to use this routine for lattice gas systems.
85
"""
86
abstract type MCRoutine end
87

88
"""
89
    abstract type MCRoutineParallel <: MCRoutine
90
(Internal) An abstract type representing a parallel Monte Carlo routine.
91
"""
92
abstract type MCRoutineParallel <: MCRoutine end
93

94
"""
95
    struct MCRandomWalkMaxE <: MCRoutine
96
A type for generating a new walker by performing a random walk for decorrelation on the highest-energy walker.
97
"""
98
struct MCRandomWalkMaxE <: MCRoutine 
99
    dims::Vector{Int64}
100
    function MCRandomWalkMaxE(dims::Vector{Int64}=[1, 2, 3])
84✔
101
        new(dims)
96✔
102
    end
103
end
104

105
"""
106
    struct MCRandomWalkClone <: MCRoutine
107
A type for generating a new walker by cloning an existing walker and performing a random walk for decorrelation.
108
"""
109
struct MCRandomWalkClone <: MCRoutine 
110
    dims::Vector{Int64}
111
    function MCRandomWalkClone(;dims::Vector{Int64}=[1, 2, 3])
63✔
112
        new(dims)
36✔
113
    end
114
end
115

116
"""
117
    struct MCRandomWalkCloneParallel <: MCRoutineParallel
118
A type for generating a new walker by cloning an existing walker and performing a random walk for decorrelation in parallel.
119
"""
120
struct MCRandomWalkCloneParallel <: MCRoutineParallel
121
    dims::Vector{Int64}
122
    function MCRandomWalkCloneParallel(;dims::Vector{Int64}=[1, 2, 3])
21✔
123
        new(dims)
12✔
124
    end
125
end
126

127
"""
128
    MCRandomWalkMaxEParallel <: MCRoutineParallel
129
A type for generating a new walker by performing a random walk for decorrelation on the highest-energy walker(s) in parallel.
130
"""
131
struct MCRandomWalkMaxEParallel <: MCRoutineParallel
132
    dims::Vector{Int64}
133
    function MCRandomWalkMaxEParallel(;dims::Vector{Int64}=[1, 2, 3])
21✔
134
        new(dims)
12✔
135
    end
136
end
137

138
"""
139
    struct MCNewSample <: MCRoutine
140
A type for generating a new walker from a random configuration. Currently, it is intended to use this routine for lattice gas systems.
141
"""
142
struct MCNewSample <: MCRoutine end
16✔
143

144
""" 
145
    struct MCMixedMoves <: MCRoutine
146
A type for generating a new walker by performing random walks and swapping atoms. Currently, it is intended to use this routine for
147
multi-component systems. The actual number of random walks and swaps to perform is determined by the weights of the fields `walks_freq` and `swaps_freq`.
148
For example, if `walks_freq=4` and `swaps_freq=1`, then the probability of performing a random walk is 4/5, and the probability of performing a swap is 1/5.
149

150
# Fields
151
- `walks_freq::Int`: The frequency of random walks to perform.
152
- `swaps_freq::Int`: The frequency of atom swaps to perform.
153
"""
154
mutable struct MCMixedMoves <: MCRoutine
155
    walks_freq::Int
12✔
156
    swaps_freq::Int
157
end
158

159
"""
160
    struct MCRejectionSampling <: MCRoutine
161
A type for generating a new walker by performing rejection sampling. Currently, it is intended to use this routine for lattice gas systems.
162
"""
163
struct MCRejectionSampling <: MCRoutine end
4✔
164

165
"""
166
    sort_by_energy!(liveset::LJAtomWalkers)
167

168
Sorts the walkers in the liveset by their energy in descending order.
169

170
# Arguments
171
- `liveset::LJAtomWalkers`: The liveset of walkers to be sorted.
172

173
# Returns
174
- `liveset::LJAtomWalkers`: The sorted liveset.
175
"""
176
function sort_by_energy!(liveset::AbstractLiveSet)
280✔
177
    sort!(liveset.walkers, by = x -> x.energy, rev=true)
1,506✔
178
    # println("after sort ats[1].system_data.energy: ", ats[1].system_data.energy)
179
    return liveset
280✔
180
end
181

182
"""
183
    update_iter!(liveset::AtomWalkers)
184

185
Update the iteration count for each walker in the liveset.
186

187
# Arguments
188
- `liveset::AtomWalkers`: The set of walkers to update.
189

190
"""
191
function update_iter!(liveset::AbstractLiveSet)
263✔
192
    for at in liveset.walkers
264✔
193
        at.iter += 1
777✔
194
    end
777✔
195
end
196

197
"""
198
    estimate_temperature(n_walker::Int, n_cull::Int, ediff::Float64)
199
Estimate the temperature for the nested sampling algorithm from dlog(ω)/dE.
200
"""
201
function estimate_temperature(n_walkers::Int, n_cull::Int, ediff::Float64, iter::Int=1)
×
202
    ω = (n_cull / (n_walkers + n_cull)) * (n_walkers / (n_walkers + n_cull))^iter
×
203
    β = log(ω) / ediff
×
204
    kb = 8.617333262145e-5 # eV/K
×
205
    T = 1 / (kb * β) # in Kelvin
×
206
    return T
×
207
end
208

209

210
"""
211
    nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutine)
212

213
Perform a single step of the nested sampling algorithm using the Monte Carlo random walk routine.
214

215
Arguments
216
- `liveset::AtomWalkers`: The set of atom walkers.
217
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
218
- `mc_routine::MCRoutine`: The Monte Carlo routine for generating new samples. See [`MCRoutine`](@ref).
219

220
Returns
221
- `iter`: The iteration number after the step.
222
- `emax`: The highest energy recorded during the step.
223
- `liveset`: The updated set of atom walkers.
224
- `ns_params`: The updated nested sampling parameters.
225
"""
226
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutine)
112✔
227
    sort_by_energy!(liveset)
112✔
228
    ats = liveset.walkers
112✔
229
    lj = liveset.lj_potential
112✔
230
    iter::Union{Missing,Int} = missing
112✔
231
    emax::Union{Missing,typeof(0.0u"eV")} = liveset.walkers[1].energy
112✔
232
    if mc_routine isa MCRandomWalkMaxE
112✔
233
        to_walk = deepcopy(ats[1])
192✔
234
    elseif mc_routine isa MCRandomWalkClone
16✔
235
        to_walk = deepcopy(rand(ats[2:end]))
24✔
236
    else
237
        error("Unsupported MCRoutine type: $mc_routine")
4✔
238
    end
239
    if length(mc_routine.dims) == 3
108✔
240
        accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
100✔
241
    elseif length(mc_routine.dims) == 2
8✔
242
        accept, rate, at = MC_random_walk_2D!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax; dims=mc_routine.dims)
4✔
243
        # @info "Doing a 2D random walk"
244
    elseif length(mc_routine.dims) == 1
4✔
245
        error("Unsupported dimensions: $(mc_routine.dims)")
4✔
246
    end
247
    # accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
248
    # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: $(round(ns_params.step_size; sigdigits=4))"
249
    if accept
104✔
250
        push!(ats, at)
94✔
251
        popfirst!(ats)
94✔
252
        update_iter!(liveset)
94✔
253
        ns_params.fail_count = 0
94✔
254
        iter = liveset.walkers[1].iter
94✔
255
    else
256
        # @warn "Failed to accept MC move"
257
        emax = missing
10✔
258
        ns_params.fail_count += 1
10✔
259
    end
260
    adjust_step_size(ns_params, rate)
174✔
261
    return iter, emax, liveset, ns_params
104✔
262
end
263

264

265

266
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutineParallel)
28✔
267
    sort_by_energy!(liveset)
28✔
268
    ats = liveset.walkers
28✔
269
    lj = liveset.lj_potential
28✔
270
    iter::Union{Missing,Int} = missing
28✔
271
    emax::Union{Vector{Missing},Vector{typeof(0.0u"eV")}} = [liveset.walkers[i].energy for i in 1:nworkers()]
56✔
272

273
    if mc_routine isa MCRandomWalkMaxEParallel
28✔
274
        to_walk_inds = 1:nworkers()
8✔
275
    elseif mc_routine isa MCRandomWalkCloneParallel
24✔
276
        to_walk_inds = sort!(sample(2:length(ats), nworkers()))
24✔
277
    end
278
    
279
    to_walks = deepcopy.(ats[to_walk_inds])
28✔
280

281
    if length(mc_routine.dims) == 3
28✔
282
        random_walk_function = MC_random_walk!
28✔
283
    elseif length(mc_routine.dims) == 2
×
284
        random_walk_function = MC_random_walk_2D!
×
285
    else
286
        error("Unsupported dimensions: $(mc_routine.dims)")
×
287
    end
288

289

290
    walking = [remotecall(random_walk_function, workers()[i], ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax[end]) for (i,to_walk) in enumerate(to_walks)]
28✔
291
    walked = fetch.(walking)
28✔
292
    finalize.(walking) # finalize the remote calls, clear the memory
28✔
293

294
    accepted_rates = [x[2] for x in walked]
28✔
295
    rate = mean(accepted_rates)
28✔
296

297
    if prod([x[1] for x in walked]) == 0 # if any of the walkers failed
28✔
298
        ns_params.fail_count += 1
×
299
        emax = [missing]
×
300
        return iter, emax[end], liveset, ns_params
×
301
    end
302

303
    # sort!(walked, by = x -> x[3].energy, rev=true)
304
    # filter!(x -> x[1], walked) # remove the failed ones
305

306
    for (i, at) in enumerate(walked)
28✔
307
        ats[i] = at[3]
56✔
308
    end
56✔
309

310
    update_iter!(liveset)
28✔
311
    ns_params.fail_count = 0
28✔
312
    iter = liveset.walkers[1].iter
28✔
313

314
    adjust_step_size(ns_params, rate)
40✔
315
    return iter, emax[end], liveset, ns_params
28✔
316
end
317

318
function nested_sampling_step!(liveset::LJSurfaceWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutineParallel)
8✔
319
    sort_by_energy!(liveset)
8✔
320
    ats = liveset.walkers
8✔
321
    lj = liveset.lj_potential
8✔
322
    iter::Union{Missing,Int} = missing
8✔
323
    emax::Union{Vector{Missing},Vector{typeof(0.0u"eV")}} = [liveset.walkers[i].energy for i in 1:nworkers()]
16✔
324

325
    if mc_routine isa MCRandomWalkMaxEParallel
8✔
326
        to_walk_inds = 1:nworkers()
8✔
327
    elseif mc_routine isa MCRandomWalkCloneParallel
4✔
328
        to_walk_inds = sort!(sample(2:length(ats), nworkers()))
4✔
329
    end
330
    
331
    to_walks = deepcopy.(ats[to_walk_inds])
8✔
332

333
    if length(mc_routine.dims) == 3
8✔
334
        random_walk_function = MC_random_walk!
8✔
335
    elseif length(mc_routine.dims) == 2
×
336
        random_walk_function = MC_random_walk_2D!
×
337
    else
338
        error("Unsupported dimensions: $(mc_routine.dims)")
×
339
    end
340

341

342
    walking = [remotecall(random_walk_function, workers()[i], ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax[end], liveset.surface) for (i,to_walk) in enumerate(to_walks)]
8✔
343
    walked = fetch.(walking)
8✔
344
    finalize.(walking) # finalize the remote calls, clear the memory
8✔
345

346
    accepted_rates = [x[2] for x in walked]
8✔
347
    rate = mean(accepted_rates)
8✔
348

349
    if prod([x[1] for x in walked]) == 0 # if any of the walkers failed
8✔
350
        ns_params.fail_count += 1
×
351
        emax = [missing]
×
352
        return iter, emax[end], liveset, ns_params
×
353
    end
354

355
    # sort!(walked, by = x -> x[3].energy, rev=true)
356
    # filter!(x -> x[1], walked) # remove the failed ones
357

358
    for (i, at) in enumerate(walked)
8✔
359
        ats[i] = at[3]
16✔
360
    end
16✔
361

362
    update_iter!(liveset)
8✔
363
    ns_params.fail_count = 0
8✔
364
    iter = liveset.walkers[1].iter
8✔
365

366
    adjust_step_size(ns_params, rate)
9✔
367
    return iter, emax[end], liveset, ns_params
8✔
368
end
369

370
function nested_sampling_step!(liveset::LJSurfaceWalkers, ns_params::NestedSamplingParameters, mc_routine::MCRoutine)
16✔
371
    sort_by_energy!(liveset)
16✔
372
    ats = liveset.walkers
16✔
373
    lj = liveset.lj_potential
16✔
374
    iter::Union{Missing,Int} = missing
16✔
375
    emax::Union{Missing,typeof(0.0u"eV")} = liveset.walkers[1].energy
16✔
376
    if mc_routine isa MCRandomWalkMaxE
16✔
377
        to_walk = deepcopy(ats[1])
8✔
378
    elseif mc_routine isa MCRandomWalkClone
12✔
379
        to_walk = deepcopy(rand(ats[2:end]))
16✔
380
    else
381
        error("Unsupported MCRoutine type: $mc_routine")
4✔
382
    end
383
    if length(mc_routine.dims) == 3
12✔
384
        accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax, liveset.surface)
8✔
385
    else
386
        error("Unsupported dimensions: $(mc_routine.dims)")
4✔
387
    end
388
    # accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
389
    # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: $(round(ns_params.step_size; sigdigits=4))"
390
    if accept
8✔
391
        push!(ats, at)
8✔
392
        popfirst!(ats)
8✔
393
        update_iter!(liveset)
8✔
394
        ns_params.fail_count = 0
8✔
395
        iter = liveset.walkers[1].iter
8✔
396
    else
397
        # @warn "Failed to accept MC move"
398
        emax = missing
×
399
        ns_params.fail_count += 1
×
400
    end
401
    adjust_step_size(ns_params, rate)
8✔
402
    return iter, emax, liveset, ns_params
8✔
403
end
404

405
"""
406
    nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCMixedMoves)
407

408
Perform a single step of the nested sampling algorithm using the Monte Carlo mixed moves routine.
409

410
Arguments
411
- `liveset::AtomWalkers`: The set of atom walkers.
412
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
413
- `mc_routine::MCMixedMoves`: The Monte Carlo mixed moves routine.
414

415
Returns
416
- `iter`: The iteration number after the step.
417
- `emax`: The highest energy recorded during the step.
418
- `liveset`: The updated set of atom walkers.
419
- `ns_params`: The updated nested sampling parameters.
420
"""
421
function nested_sampling_step!(liveset::AtomWalkers, ns_params::NestedSamplingParameters, mc_routine::MCMixedMoves)
4✔
422
    sort_by_energy!(liveset)
4✔
423
    ats = liveset.walkers
4✔
424
    lj = liveset.lj_potential
4✔
425
    iter::Union{Missing,Int} = missing
4✔
426
    emax::Union{Missing,typeof(0.0u"eV")} = liveset.walkers[1].energy
4✔
427

428
    # clone one of the lower energy walkers
429
    to_walk = deepcopy(rand(ats[2:end]))
8✔
430
    # determine whether to perform a random walk or a swap
431
    swap_prob = mc_routine.swaps_freq / (mc_routine.walks_freq + mc_routine.swaps_freq)
4✔
432
    
433
    # @show mc_routine
434
    if rand() > swap_prob
4✔
435
        accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, lj, ns_params.step_size, emax)
4✔
436
        @info "Swap move performed at iter: $(liveset.walkers[1].iter), accepted: $accept"
4✔
437
        # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: $(round(ns_params.step_size; sigdigits=4))"
438
    else
439
        accept, rate, at = MC_random_swap!(ns_params.mc_steps, to_walk, lj, emax)
×
440
        # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $(round(rate; sigdigits=4)), emax: $(round(typeof(1.0u"eV"), emax; sigdigits=10)), is_accepted: $accept, step_size: swap"
441
    end
442
    
443
    if accept
4✔
444
        push!(ats, at)
4✔
445
        popfirst!(ats)
4✔
446
        update_iter!(liveset)
4✔
447
        ns_params.fail_count = 0
4✔
448
        iter = liveset.walkers[1].iter
4✔
449
    else
450
        # @warn "Failed to accept MC move"
451
        emax = missing
×
452
        ns_params.fail_count += 1
×
453
    end
454
    adjust_step_size(ns_params, rate)
4✔
455
    return iter, emax, liveset, ns_params
4✔
456
end
457

458
"""
459
    nested_sampling_step!(liveset::LatticeGasWalkers, ns_params::LatticeNestedSamplingParameters, mc_routine::MCRoutine)
460

461
Perform a single step of the nested sampling algorithm.
462

463
This function takes a `liveset` of lattice gas walkers, `ns_params` containing the parameters for nested sampling, and `mc_routine` representing the Monte Carlo 
464
routine for generating new samples. It performs a single step of the nested sampling algorithm by updating the liveset with a new walker.
465

466
## Arguments
467
- `liveset::LatticeGasWalkers`: The liveset of lattice gas walkers.
468
- `ns_params::LatticeNestedSamplingParameters`: The parameters for nested sampling.
469
- `mc_routine::MCRoutine`: The Monte Carlo routine for generating new samples.
470

471
## Returns
472
- `iter`: The iteration number of the liveset after the step.
473
- `emax`: The maximum energy of the liveset after the step.
474
"""
475
function nested_sampling_step!(liveset::LatticeGasWalkers, 
96✔
476
                               ns_params::NestedSamplingParameters, 
477
                               mc_routine::MCRoutine)
478
    sort_by_energy!(liveset)
96✔
479
    ats = liveset.walkers
96✔
480
    h = liveset.hamiltonian
96✔
481
    iter::Union{Missing,Int} = missing
96✔
482
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
96✔
483
    if mc_routine isa MCRandomWalkMaxE
96✔
484
        to_walk = deepcopy(ats[1])
184✔
485
    elseif mc_routine isa MCRandomWalkClone
4✔
486
        to_walk = deepcopy(rand(ats[2:end]))
8✔
487
    else
488
        error("Unsupported MCRoutine type: $mc_routine")
×
489
    end
490
    accept, rate, at = MC_random_walk!(ns_params.mc_steps, to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
96✔
491

492
    # @info "iter: $(liveset.walkers[1].iter), acceptance rate: $rate, emax: $emax, is_accepted: $accept"
493
    if accept
96✔
494
        push!(ats, at)
91✔
495
        popfirst!(ats)
91✔
496
        update_iter!(liveset)
91✔
497
        ns_params.fail_count = 0
91✔
498
        iter = liveset.walkers[1].iter
91✔
499
    else
500
        # @warn "Failed to accept MC move"
501
        emax = missing
5✔
502
        ns_params.fail_count += 1
5✔
503
    end
504
    # adjust_step_size(ns_params, rate)
505
    return iter, emax * unit(liveset.walkers[1].energy), liveset, ns_params
96✔
506
end
507

508
"""
509
    nested_sampling_step!(liveset::LatticeGasWalkers, ns_params::LatticeNestedSamplingParameters, mc_routine::MCNewSample)
510

511
Perform a single step of the nested sampling algorithm.
512

513
This function takes a `liveset` of lattice gas walkers, `ns_params` containing the parameters for nested sampling, and `mc_routine` representing the Monte Carlo routine for generating new samples. It performs a single step of the nested sampling algorithm by updating the liveset with a new walker.
514

515
## Arguments
516
- `liveset::LatticeGasWalkers`: The liveset of lattice gas walkers.
517
- `ns_params::LatticeNestedSamplingParameters`: The parameters for nested sampling.
518
- `mc_routine::MCNewSample`: The Monte Carlo routine for generating new samples.
519

520
## Returns
521
- `iter`: The iteration number of the liveset after the step.
522
- `emax`: The maximum energy of the liveset after the step.
523
- `liveset::LatticeGasWalkers`: The updated liveset after the step.
524
- `ns_params::LatticeNestedSamplingParameters`: The updated nested sampling parameters after the step.
525
"""
526
function nested_sampling_step!(liveset::LatticeGasWalkers, 
4✔
527
                               ns_params::NestedSamplingParameters, 
528
                               mc_routine::MCNewSample)
529
    sort_by_energy!(liveset)
4✔
530
    ats = liveset.walkers
4✔
531
    h = liveset.hamiltonian
4✔
532
    iter::Union{Missing,Int} = missing
4✔
533
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
4✔
534

535
    to_walk = deepcopy(ats[1])
8✔
536

537
    accept, at = MC_new_sample!(to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
4✔
538

539
    # @info "iter: $(liveset.walkers[1].iter), emax: $emax, is_accepted: $accept"
540
    if accept
4✔
541
        push!(ats, at)
2✔
542
        popfirst!(ats)
2✔
543
        update_iter!(liveset)
2✔
544
        ns_params.fail_count = 0
2✔
545
        iter = liveset.walkers[1].iter
2✔
546
    else
547
        # @warn "Failed to accept MC move"
548
        emax = missing
2✔
549
        ns_params.fail_count += 1
2✔
550
    end
551
    # adjust_step_size(ns_params, rate)
552
    return iter, emax * unit(liveset.walkers[1].energy), liveset, ns_params
4✔
553
end
554

555

556
function nested_sampling_step!(liveset::LatticeGasWalkers, 
4✔
557
                               ns_params::NestedSamplingParameters, 
558
                               mc_routine::MCRejectionSampling)
559
    sort_by_energy!(liveset)
4✔
560
    ats = liveset.walkers
4✔
561
    h = liveset.hamiltonian
4✔
562
    iter::Union{Missing,Int} = missing
4✔
563
    emax::Union{Missing,Float64} = liveset.walkers[1].energy.val
4✔
564

565
    to_walk = deepcopy(ats[1])
8✔
566

567
    accept, at = MC_rejection_sampling!(to_walk, h, emax; energy_perturb=ns_params.energy_perturbation)
4✔
568

569
    # @info "iter: $(liveset.walkers[1].iter), emax: $emax, is_accepted: $accept"
570
    if accept
4✔
571
        push!(ats, at)
4✔
572
        popfirst!(ats)
4✔
573
        update_iter!(liveset)
4✔
574
        ns_params.fail_count = 0
4✔
575
        iter = liveset.walkers[1].iter
4✔
576
    else
577
        # @warn "Failed to accept MC move"
578
        emax = missing
×
579
        ns_params.fail_count += 1
×
580
    end
581
    # adjust_step_size(ns_params, rate)
582
    return iter, emax * unit(liveset.walkers[1].energy), liveset, ns_params
4✔
583
end
584

585

586

587
"""
588
    nested_sampling(liveset::AbstractLiveSet, ns_params::NestedSamplingParameters, n_steps::Int64, mc_routine::MCRoutine; args...)
589

590
Perform a nested sampling loop for a given number of steps.
591

592
# Arguments
593
- `liveset::AbstractLiveSet`: The initial set of walkers.
594
- `ns_params::NestedSamplingParameters`: The parameters for nested sampling.
595
- `n_steps::Int64`: The number of steps to perform.
596
- `mc_routine::MCRoutine`: The Monte Carlo routine to use.
597

598
# Returns
599
- `df`: A DataFrame containing the iteration number and maximum energy for each step.
600
- `liveset`: The updated set of walkers.
601
- `ns_params`: The updated nested sampling parameters.
602
"""
603
function nested_sampling(liveset::AbstractLiveSet, 
36✔
604
                                ns_params::NestedSamplingParameters, 
605
                                n_steps::Int64, 
606
                                mc_routine::MCRoutine,
607
                                save_strategy::DataSavingStrategy)
608
    df = DataFrame(iter=Int[], emax=Float64[])
36✔
609
    for i in 1:n_steps
36✔
610
        print_info = i % save_strategy.n_info == 0
200✔
611
        write_walker_every_n(liveset.walkers[1], i, save_strategy)
200✔
612
        iter, emax, liveset, ns_params = nested_sampling_step!(liveset, ns_params, mc_routine)
215✔
613
        @debug "n_step $i, iter: $iter, emax: $emax"
200✔
614
        if ns_params.fail_count >= ns_params.allowed_fail_count
200✔
615
            @warn "Failed to accept MC move $(ns_params.allowed_fail_count) times in a row. Reset step size!"
1✔
616
            ns_params.fail_count = 0
1✔
617
            ns_params.step_size = ns_params.initial_step_size
1✔
618
        end
619
        if !(iter isa typeof(missing))
200✔
620
            push!(df, (iter, emax.val))
234✔
621
            if print_info
186✔
622
                @info "iter: $(liveset.walkers[1].iter), emax: $(emax), step_size: $(round(ns_params.step_size; sigdigits=4))"
153✔
623
            end
624
        elseif iter isa typeof(missing) && print_info
14✔
625
            @info "MC move failed, step: $(i), emax: $(liveset.walkers[1].energy), step_size: $(round(ns_params.step_size; sigdigits=4))"
6✔
626
        end
627
        write_df_every_n(df, i, save_strategy)
200✔
628
        write_ls_every_n(liveset, i, save_strategy)
200✔
629
    end
364✔
630
    return df, liveset, ns_params
36✔
631
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc