Skip to content

Commit

Permalink
feat: Analytic optimisation backed by SemioticOpt
Browse files Browse the repository at this point in the history
Modified analytic optimisation to use the OptAlgorithm interface from SemioticOpt
  • Loading branch information
anirudh2 committed Apr 17, 2023
1 parent 9230735 commit 33d049a
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 3 deletions.
84 changes: 81 additions & 3 deletions src/opt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,81 @@
# Copyright 2022-, The Graph Foundation
# SPDX-License-Identifier: MIT

"""
AnalyticOpt{T<:Real,V<:AbstractArray{T},A<:AbstractArray{T},S<:AbstractVector{<:Hook}} <: OptAlgorithm
Optimise the indexing reward analytically.
# Fields
- `x::V` is the current best guess for the solution. Typically zeros.
- `Ω::V` is the allocation vector of other indexers.
- `ψ::A` is the signal vector.
- `σ::T` is the stake.
- `hooks::S` are the hooks
# Example
```julia
julia> using AllocationOpt
julia> using SemioticOpt
julia> x = zeros(2)
julia> Ω = [1.0, 1.0]
julia> ψ = [10.0, 10.0]
julia> σ = 5.0
julia> alg = AllocationOpt.AnalyticOpt(;
x=x, Ω=Ω, ψ=ψ, σ=σ, hooks=[StopWhen((a; kws...) -> kws[:i] > 1)]
)
julia> f = x -> x # This doesn't matter. `f` isn't used by the algorithm.
julia> alg = minimize!(f, alg)
julia> SemioticOpt.x(alg)
2-element Vector{Float64}:
2.5
2.5
```
"""
Base.@kwdef struct AnalyticOpt{
T<:Real,V<:AbstractVector{T},A<:AbstractArray{T},S<:AbstractVector{<:Hook}
} <: SemioticOpt.OptAlgorithm
x::V
Ω::V
ψ::A
σ::T
hooks::S
end

"""
x(a::AnalyticOpt)
Return the current best guess for the solution.
"""
SemioticOpt.x(a::AnalyticOpt) = a.x
"""
x!(a::AnalyticOpt, v)
In-place setting of `a.x` to `v`
See [`SemioticOpt.x`](@ref).
"""
function SemioticOpt.x!(a::AnalyticOpt, v)
a.x .= v
return a
end
SemioticOpt.hooks(a::AnalyticOpt) = a.hooks

"""
iteration(::Function, a::AnalyticOpt)
Perform the analytic optimisation.
"""
function SemioticOpt.iteration(::Function, a::AnalyticOpt)
Ω = a.Ω
ψ = a.ψ
σ = a.σ
v = dual(Ω, ψ, σ)
x = primal(Ω, ψ, v)
y = σsimplex(x, σ)
return y
end

"""
optimizeanalytic(Ω, ψ, σ)
Expand All @@ -18,9 +93,12 @@ julia> AllocationOpt.optimizeanalytic(Ω, ψ, σ)
```
"""
function optimizeanalytic(Ω, ψ, σ)
v = dual(Ω, ψ, σ)
x = primal(Ω, ψ, v)
y = σsimplex(x, σ)
f = x -> x # This doesn't matter; we're not using it
alg = AllocationOpt.AnalyticOpt(;
x=zero(ψ), Ω=Ω, ψ=ψ, σ=σ, hooks=[StopWhen((a; kws...) -> kws[:i] > 1)]
)
minimize!(f, alg)
y = SemioticOpt.x(alg)
return y
end

Expand Down
34 changes: 34 additions & 0 deletions test/opt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@
# SPDX-License-Identifier: MIT

@testset "opt" begin
@testset "SemioticOpt analytic" begin
f = x -> x # This doesn't matter; analytic opt doesn't use it

x = zeros(2)
Ω = [1.0, 1.0]
ψ = [10.0, 10.0]
σ = 5.0
alg = AllocationOpt.AnalyticOpt(;
x=x, Ω=Ω, ψ=ψ, σ=σ, hooks=[StopWhen((a; kws...) -> kws[:i] > 1)]
)
alg = minimize!(f, alg)
@test isapprox(SemioticOpt.x(alg), [2.5, 2.5]; atol=0.1)

x = zeros(2)
Ω = [1.0, 1.0]
ψ = [0.0, 10.0]
σ = 5.0
alg = AllocationOpt.AnalyticOpt(;
x=x, Ω=Ω, ψ=ψ, σ=σ, hooks=[StopWhen((a; kws...) -> kws[:i] > 1)]
)
alg = minimize!(f, alg)
@test isapprox(SemioticOpt.x(alg), [0.0, 5.0]; atol=0.1)

x = zeros(2)
Ω = [1.0, 10000.0]
ψ = [10.0, 10.0]
σ = 5.0
alg = AllocationOpt.AnalyticOpt(;
x=x, Ω=Ω, ψ=ψ, σ=σ, hooks=[StopWhen((a; kws...) -> kws[:i] > 1)]
)
alg = minimize!(f, alg)
@test isapprox(SemioticOpt.x(alg), [5.0, 0.0]; atol=0.1)
end

@testset "optimizeanalytic" begin
Ω = [1.0, 1.0]
ψ = [10.0, 10.0]
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ using CSV
using TheGraphData
using JSON
using Mocking
using SemioticOpt
using AllocationOpt
using Test

Expand Down

0 comments on commit 33d049a

Please sign in to comment.