Skip to content

Commit 41c1308

Browse files
author
Alexey Stukalov
committed
sem_optimizer_subtype(engine)
internal method returning the type that implements SemOptimizer{engine}
1 parent f4f9280 commit 41c1308

6 files changed

Lines changed: 31 additions & 20 deletions

File tree

docs/src/developer/optimizer.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Custom optimizer types
22

3-
The optimizer part of a model connects it to the optimization backend.
3+
The optimizer part of a model connects it to the optimization backend.
44
Let's say we want to implement a new optimizer as `SemOptimizerName`. The first part of the implementation is very similar to loss functions, so we just show the implementation of `SemOptimizerOptim` here as a reference:
55

66
```julia
@@ -12,7 +12,7 @@ mutable struct SemOptimizerName{A, B} <: SemOptimizer{:Name}
1212
options::B
1313
end
1414

15-
SemOptimizer{:Name}(args...; kwargs...) = SemOptimizerName(args...; kwargs...)
15+
SEM.sem_optimizer_subtype(::Val{:Name}) = SemOptimizerName
1616

1717
SemOptimizerName(;
1818
algorithm = LBFGS(),

ext/SEMNLOptExt/NLopt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ struct SemOptimizerNLopt <: SemOptimizer{:NLopt}
8585
inequality_constraints::Vector{NLoptConstraint}
8686
end
8787

88+
SEM.sem_optimizer_subtype(::Val{:NLopt}) = SemOptimizerNLopt
89+
8890
############################################################################################
8991
### Constructor
9092
############################################################################################
@@ -117,8 +119,6 @@ function SemOptimizerNLopt(;
117119
)
118120
end
119121

120-
SEM.SemOptimizer{:NLopt}(args...; kwargs...) = SemOptimizerNLopt(args...; kwargs...)
121-
122122
############################################################################################
123123
### Recommended methods
124124
############################################################################################

ext/SEMProximalOptExt/ProximalAlgorithms.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ mutable struct SemOptimizerProximal{A, B, C} <: SemOptimizer{:Proximal}
3030
operator_h::C
3131
end
3232

33-
SEM.SemOptimizer{:Proximal}(args...; kwargs...) = SemOptimizerProximal(args...; kwargs...)
34-
3533
SemOptimizerProximal(;
3634
algorithm = ProximalAlgorithms.PANOC(),
3735
operator_g,
3836
operator_h = nothing,
3937
kwargs...,
4038
) = SemOptimizerProximal(algorithm, operator_g, operator_h)
4139

40+
SEM.sem_optimizer_subtype(::Val{:Proximal}) = SemOptimizerProximal
41+
4242
############################################################################################
4343
### Recommended methods
4444
############################################################################################

src/optimizer/Empty.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ an optimizer part.
1111
"""
1212
struct SemOptimizerEmpty <: SemOptimizer{:Empty} end
1313

14-
############################################################################################
15-
### Constructor
16-
############################################################################################
17-
18-
SemOptimizer{:Empty}() = SemOptimizerEmpty()
14+
sem_optimizer_subtype(::Val{:Empty}) = SemOptimizerEmpty
1915

2016
############################################################################################
2117
### Recommended methods

src/optimizer/abstract.jl

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
1-
SemOptimizer(args...; engine::Symbol = :Optim, kwargs...) =
2-
SemOptimizer{engine}(args...; kwargs...)
3-
4-
# fallback optimizer constructor
5-
function SemOptimizer{E}(args...; kwargs...) where {E}
6-
if E == :NLOpt
1+
# throw unsupported engine error
2+
function throw_engine_error(E)
3+
if typeof(E) !== Symbol
4+
throw(ArgumentError("engine argument must be a Symbol."))
5+
elseif E == :NLopt
76
error("$E optimizer requires \"using NLopt\".")
87
elseif E == :Proximal
98
error("$E optimizer requires \"using ProximalAlgorithms\".")
109
else
11-
error("$E optimizer is not supported.")
10+
error("$E optimizer engine is not supported.")
1211
end
1312
end
1413

14+
# return the type implementing SemOptimizer{engine}
15+
# the method should be overridden in the extension
16+
sem_optimizer_subtype(engine::Symbol) = sem_optimizer_subtype(Val(engine))
17+
18+
# fallback method for unsupported engines
19+
sem_optimizer_subtype(::Val{E}) where {E} = throw_engine_error(E)
20+
21+
# default constructor that dispatches to the engine-specific type
22+
SemOptimizer(::Val{E}, args...; kwargs...) where {E} =
23+
sem_optimizer_subtype(E)(args...; kwargs...)
24+
25+
SemOptimizer{E}(args...; kwargs...) where {E} = SemOptimizer(Val(E), args...; kwargs...)
26+
27+
SemOptimizer(args...; engine::Symbol = :Optim, kwargs...) =
28+
SemOptimizer(Val(engine), args...; kwargs...)
29+
1530
"""
1631
optimizer_engine(::Type{<:SemOptimizer})
1732
optimizer_engine(::SemOptimizer)

src/optimizer/optim.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ mutable struct SemOptimizerOptim{A, B} <: SemOptimizer{:Optim}
6363
options::B
6464
end
6565

66-
SemOptimizer{:Optim}(args...; kwargs...) = SemOptimizerOptim(args...; kwargs...)
67-
6866
SemOptimizerOptim(;
6967
algorithm = LBFGS(),
7068
options = Optim.Options(; f_reltol = 1e-10, x_abstol = 1.5e-8),
7169
kwargs...,
7270
) = SemOptimizerOptim(algorithm, options)
7371

72+
sem_optimizer_subtype(::Val{:Optim}) = SemOptimizerOptim
73+
7474
############################################################################################
7575
### Recommended methods
7676
############################################################################################

0 commit comments

Comments
 (0)