Skip to content

Commit

Permalink
Unit tests for stopping criteria and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelbailo committed Mar 7, 2024
1 parent 0eef95a commit 24816ca
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 68 deletions.
6 changes: 3 additions & 3 deletions docs/src/low_level.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Low-level interface

Internally, the `minimise` routine relies on two constructs: the `ParticleDynamic` and a `ConsensusBasedXMethod`.
Internally, the `minimise` routine relies on two constructs: the `ParticleDynamic` and a `CBXMethod`.

## ConsensusBasedXLowLevel

Expand Down Expand Up @@ -31,15 +31,15 @@ ConsensusBasedX.ParticleDynamicCache

## `ConsensusBasedOptimisation`

The `ConsensusBasedOptimisation` struct (of type `ConsensusBasedXMethod`) defines the details of the *consensus-based optimisation method* (function evaluations, consensus point...).
The `ConsensusBasedOptimisation` struct (of type `CBXMethod`) defines the details of the *consensus-based optimisation method* (function evaluations, consensus point...).

```@docs
ConsensusBasedX.ConsensusBasedOptimisation
```

### `ConsensusBasedOptimisationCache`

`ConsensusBasedOptimisation` requires a cache, `ConsensusBasedOptimisationCache` (of type `ConsensusBasedXMethodCache`). This can be constructed with:
`ConsensusBasedOptimisation` requires a cache, `ConsensusBasedOptimisationCache` (of type `CBXMethodCache`). This can be constructed with:
```@docs
ConsensusBasedX.construct_method_cache
```
Expand Down
4 changes: 2 additions & 2 deletions docs/src/noise_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ By default, ConsensusBasedX.jl uses so-called *isotropic noise* (option `noise =
```math
\mathrm{d}X_i(t) = \cdots + \sqrt{2} \sigma \left| X_i(t) - V(t) \right| \mathrm{d}W_i(t),
```
where ``W_i`` are independent Brownian processes. The intensity of the noise depends on the distance of each particle to the consensus point, ``\left| X_i(t) - V(t) \right|``.
where ``W_i`` are independent Brownian processes. The intensity of the noise depends on the distance of each particle to the consensus point, ``\left| X_i(t) - V(t) \right|``. [Full-code example](https://github.com/PdIPS/ConsensusBasedX.jl/blob/main/examples/advanced_usage/isotropic_noise.jl).

## Anisotropic noise

ConsensusBasedX.jl also offers *anisotropic noise*, given by
```math
\mathrm{d}X_i(t) = \cdots + \sqrt{2} \sigma \,\mathrm{diag} \left( X_i(t) - V(t) \right) \mathrm{d}W_i(t).
```
The intensity of the noise now varies along each dimension. This can be selected with the option `noise = :AnisotropicNoise`.
The intensity of the noise now varies along each dimension. This can be selected with the option `noise = :AnisotropicNoise`. [Full-code example](https://github.com/PdIPS/ConsensusBasedX.jl/blob/main/examples/advanced_usage/anisotropic_noise.jl).
6 changes: 6 additions & 0 deletions examples/advanced_usage/anisotropic_noise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using ConsensusBasedX

f(x) = ConsensusBasedX.Ackley(x, shift = 1)

config = (; D = 2, noise = :AnisotropicNoise)
minimise(f, config)
6 changes: 6 additions & 0 deletions examples/advanced_usage/isotropic_noise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using ConsensusBasedX

f(x) = ConsensusBasedX.Ackley(x, shift = 1)

config = (; D = 2, noise = :IsotropicNoise)
minimise(f, config)
6 changes: 4 additions & 2 deletions examples/low_level/low_level.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ f(x) = ConsensusBasedX.Ackley(x, shift = 1)
X₀ = [[rand(config.D) for n 1:(config.N)] for m 1:(config.M)]

correction = HeavisideCorrection()
method = ConsensusBasedOptimisation(f, correction, config.α, config.λ, config.σ)
noise = IsotropicNoise
method =
ConsensusBasedOptimisation(f, correction, noise, config.α, config.λ, config.σ)

Δt = 0.1
particle_dynamic = ParticleDynamic(method, Δt)
Expand All @@ -25,4 +27,4 @@ finalise_dynamic!(particle_dynamic, particle_dynamic_cache)

out = wrap_output(X₀, particle_dynamic, particle_dynamic_cache)

@show out.minimiser # should be close to [1, 1]
out.minimiser # should be close to [1, 1]
6 changes: 4 additions & 2 deletions examples/low_level/manual_stepping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ f(x) = ConsensusBasedX.Ackley(x, shift = 1)
X₀ = [[rand(config.D) for n 1:(config.N)] for m 1:(config.M)]

correction = HeavisideCorrection()
method = ConsensusBasedOptimisation(f, correction, config.α, config.λ, config.σ)
noise = IsotropicNoise
method =
ConsensusBasedOptimisation(f, correction, noise, config.α, config.λ, config.σ)

Δt = 0.1
particle_dynamic = ParticleDynamic(method, Δt)
Expand All @@ -31,4 +33,4 @@ finalise_dynamic!(particle_dynamic, particle_dynamic_cache)

out = wrap_output(X₀, particle_dynamic, particle_dynamic_cache)

@show out.minimiser # should be close to [1, 1]
out.minimiser # should be close to [1, 1]
14 changes: 7 additions & 7 deletions src/CBO/ConsensusBasedOptimisation.jl → src/CBO/CBO.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ ConsensusBasedOptimisation
Fields:
- `f`, the objective function.
- `correction<:ConsensusBasedXCorrection`, a correction term.
- `correction<:CBXCorrection`, a correction term.
- `α::Float64`, the the exponential weight parameter.
- `λ::Float64`, the drift strengh.
- `σ::Float64`, the noise strengh.
"""
mutable struct ConsensusBasedOptimisation{
TF,
TCorrection <: ConsensusBasedXCorrection,
TCorrection <: CBXCorrection,
TNoise <: Noises,
} <: ConsensusBasedXMethod
} <: CBXMethod
f::TF
correction::TCorrection
noise::TNoise
Expand All @@ -26,7 +26,7 @@ end

@config function construct_CBO(
f,
correction::ConsensusBasedXCorrection,
correction::CBXCorrection,
noise::Noises;
α::Real = 10,
λ::Real = 1,
Expand Down Expand Up @@ -67,7 +67,7 @@ Fields:
- `max_evaluations::Float64`, the maximum number of `f` evaluations.
- `evaluations::Vector{Int}`, the current number of `f` evaluations.
"""
mutable struct ConsensusBasedOptimisationCache{T} <: ConsensusBasedXMethodCache
mutable struct ConsensusBasedOptimisationCache{T} <: CBXMethodCache
consensus::Vector{Vector{T}}
consensus_energy::Vector{T}
consensus_energy_previous::Vector{T}
Expand Down Expand Up @@ -133,12 +133,12 @@ end
construct_method_cache(
config::NamedTuple,
X₀::AbstractArray,
method::ConsensusBasedXMethod,
method::CBXMethod,
particle_dynamic::ParticleDynamic,
)
```
A constructor helper for `ConsensusBasedXMethodCache`.
A constructor helper for `CBXMethodCache`.
"""
construct_method_cache

Expand Down
4 changes: 2 additions & 2 deletions src/CBO/CBO_method.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function compute_CBO_consensus!(
method::ConsensusBasedOptimisation,
method_cache::ConsensusBasedOptimisationCache,
method::CBXMethod,
method_cache::CBXMethodCache,
particle_dynamic::ParticleDynamic,
particle_dynamic_cache::ParticleDynamicCache,
m::Int,
Expand Down
6 changes: 3 additions & 3 deletions src/CBO/corrections.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
struct NoCorrection <: ConsensusBasedXCorrection end
struct NoCorrection <: CBXCorrection end
(c::NoCorrection)(s::Real) = 1.0

struct HeavisideCorrection <: ConsensusBasedXCorrection end
struct HeavisideCorrection <: CBXCorrection end
(c::HeavisideCorrection)(s::Real) = 1.0 * (s > 0)

struct RegularisedHeavisideCorrection <: ConsensusBasedXCorrection
struct RegularisedHeavisideCorrection <: CBXCorrection
ε::Float64
end
(c::RegularisedHeavisideCorrection)(s::Real) = (1 + tanh(s / c.ε)) / 2
18 changes: 10 additions & 8 deletions src/CBO/is_method_pending.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,37 @@ function is_method_pending(
particle_dynamic_cache::ParticleDynamicCache,
m::Int,
)
pending_energy_threshold = is_method_pending_energy_threshold(
if !is_method_pending_energy_threshold(
particle_dynamic.method,
particle_dynamic_cache.method_cache,
particle_dynamic,
particle_dynamic_cache,
m,
)
return false, "energy_threshold"
end

pending_energy_tolerance = is_method_pending_energy_tolerance(
if !is_method_pending_energy_tolerance(
particle_dynamic.method,
particle_dynamic_cache.method_cache,
particle_dynamic,
particle_dynamic_cache,
m,
)
return false, "energy_tolerance"
end

pending_max_evaluations = is_method_pending_max_evaluations(
if !is_method_pending_max_evaluations(
particle_dynamic.method,
particle_dynamic_cache.method_cache,
particle_dynamic,
particle_dynamic_cache,
m,
)
return false, "max_evaluations"
end

pending =
pending_energy_threshold &&
pending_energy_tolerance &&
pending_max_evaluations
return pending
return true, "method_pending"
end

function is_method_pending_energy_threshold(
Expand Down
2 changes: 1 addition & 1 deletion src/ConsensusBasedX.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ include("./dynamics/benchmark_dynamic.jl")
include("./dynamics/is_dynamic_pending.jl")
include("./dynamics/run_dynamic.jl")

include("./CBO/ConsensusBasedOptimisation.jl")
include("./CBO/CBO.jl")
include("./CBO/CBO_method.jl")
include("./CBO/corrections.jl")
include("./CBO/is_method_pending.jl")
Expand Down
9 changes: 7 additions & 2 deletions src/ConsensusBasedXLowLevel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module ConsensusBasedXLowLevel
using Reexport

@reexport import ..AnisotropicNoise,
..ConsensusBasedXMethod,
..ConsensusBasedXMethodCache,
..CBXMethod,
..CBXMethodCache,
..ConsensusBasedOptimisation,
..ConsensusBasedOptimisationCache,
..HeavisideCorrection,
Expand All @@ -24,11 +24,16 @@ using Reexport
..Quadratic,
..compute_dynamic!,
..compute_dynamic_step!,
..construct_CBO,
..construct_method_cache,
..construct_particle_dynamic,
..construct_particle_dynamic_cache,
..finalise_dynamic!,
..initialise_particles,
..initialise_particle_dynamic_cache!,
..initialise_dynamic!,
..is_dynamic_pending,
..parse_config,
..wrap_output

end
25 changes: 17 additions & 8 deletions src/dynamics/ParticleDynamics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ ParticleDynamic
Fields:
- `method<:ConsensusBasedXMethod`, the optimisation method.
- `method<:CBXMethod`, the optimisation method.
- `Δt::Float64`, the time step.
"""
mutable struct ParticleDynamic{TM <: ConsensusBasedXMethod}
mutable struct ParticleDynamic{TM <: CBXMethod}
method::TM
Δt::Float64
end
Expand All @@ -29,7 +29,7 @@ Fields:
- `mode` should be set to `ParticleMode`.
- `parallelisation<:Parallelisations`, the parallelisation mode.
- `method_cache<:ConsensusBasedXMethodCache`, a cache for the `method` field of `ParticleDynamic`.
- `method_cache<:CBXMethodCache`, a cache for the `method` field of `ParticleDynamic`.
- `D::Int`, the dimension of the problem.
- `N::Int`, the number of particles per ensemble.
- `M::Int`, the number of ensembles.
Expand All @@ -45,7 +45,7 @@ Fields:
mutable struct ParticleDynamicCache{
TMode <: Modes,
TParallelisation <: Parallelisations,
TMC <: ConsensusBasedXMethodCache,
TMC <: CBXMethodCache,
TX,
TdX,
}
Expand Down Expand Up @@ -130,13 +130,13 @@ construct_particle_dynamic_cache(
)
```
A constructor helper for `ParticleDynamicCache`. Calls [`ConsensusBasedX.construct_method_cache`](@ref) to construct the corresponding `ConsensusBasedXMethodCache`.
A constructor helper for `ParticleDynamicCache`. Calls [`ConsensusBasedX.construct_method_cache`](@ref) to construct the corresponding `CBXMethodCache`.
"""
construct_particle_dynamic_cache

@config construct_method_cache(
X₀::AbstractArray,
method::ConsensusBasedXMethod,
method::CBXMethod,
particle_dynamic::ParticleDynamic,
) = nothing

Expand Down Expand Up @@ -167,13 +167,22 @@ function set_Δt!(particle_dynamic_cache::ParticleDynamicCache, Δt::Real)
particle_dynamic_cache.Δt = Δt
particle_dynamic_cache.rootΔt = sqrt(Δt)
particle_dynamic_cache.root2Δt = sqrt(2) * particle_dynamic_cache.rootΔt
set_Δt!(particle_dynamic_cache.method_cache, particle_dynamic_cache, Δt)
return nothing
end

function set_Δt!(
method_cache::CBXMethodCache,
particle_dynamic_cache::ParticleDynamicCache,
Δt::Real,
)
return nothing
end

function initialise_method_cache!(
X₀::AbstractArray,
method::ConsensusBasedXMethod,
method_cache::ConsensusBasedXMethodCache,
method::CBXMethod,
method_cache::CBXMethodCache,
particle_dynamic::ParticleDynamic,
particle_dynamic_cache::ParticleDynamicCache,
)
Expand Down
22 changes: 11 additions & 11 deletions src/dynamics/is_dynamic_pending.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ function is_dynamic_pending(
particle_dynamic_cache::ParticleDynamicCache,
m::Int,
)
pending_max_iterations = is_dynamic_pending_max_iterations(
if !is_dynamic_pending_max_iterations(
particle_dynamic,
particle_dynamic_cache,
m,
)
return false, "max_iterations"
end

pending_max_time =
is_dynamic_pending_max_time(particle_dynamic, particle_dynamic_cache, m)
if !is_dynamic_pending_max_time(particle_dynamic, particle_dynamic_cache, m)
return false, "max_time"
end

pending_method = is_method_pending(
return is_method_pending(
particle_dynamic.method,
particle_dynamic_cache.method_cache,
particle_dynamic,
particle_dynamic_cache,
m,
)

pending = pending_max_iterations && pending_max_time && pending_method
return pending
end

function is_dynamic_pending_max_iterations(
Expand All @@ -40,15 +40,15 @@ function is_dynamic_pending_max_time(
)
@expand particle_dynamic Δt
@expand particle_dynamic_cache iteration max_time
return iteration[m] * Δt <= max_time
return iteration[m] * Δt < max_time
end

function is_method_pending(
method::ConsensusBasedXMethod,
method_cache::ConsensusBasedXMethodCache,
method::CBXMethod,
method_cache::CBXMethodCache,
particle_dynamic::ParticleDynamic,
particle_dynamic_cache::ParticleDynamicCache,
m::Int,
)
return true
return true, "method_pending"

Check warning on line 53 in src/dynamics/is_dynamic_pending.jl

View check run for this annotation

Codecov / codecov/patch

src/dynamics/is_dynamic_pending.jl#L53

Added line #L53 was not covered by tests
end
Loading

0 comments on commit 24816ca

Please sign in to comment.