Skip to content

Commit

Permalink
scan_rtol
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgeny Metelkin committed May 7, 2022
1 parent f9084f0 commit f63e109
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 91 deletions.
6 changes: 2 additions & 4 deletions TODO.md
@@ -1,10 +1,8 @@
# TODO

- set modified abstol for log transformation
- add display summary for `get_endpoint` for scan_func
- check supreme in `get_endpoint`
- `loss_grad`, `scan_grad` for :LIN_EXTRAPOL, :QUADR_EXTRAPOL
- use `scale` option for `get_interval`
- remove bound for scanned parameter
- use fitting reset as an option
- remove `kwargs...` if not required
- review kwargs
- update documentation
38 changes: 23 additions & 15 deletions src/cico_one_pass.jl
Expand Up @@ -10,7 +10,8 @@ function get_right_endpoint(
),
scan_bound::Float64 = 9.0,
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3, # we have no ideas how to implement loss_tol, currently it is in `inequality_constraint!`
scan_rtol::Float64 = 0.,
loss_tol::Float64 = 0., # we have no idea how to implement loss_tol
# better results for LN_NELDERMEAD, :LD_MMA, :LD_SLSQP, :LD_CCSAQ
# worse results for :LN_COBYLA, :LN_PRAXIS
# errors for :LN_BOBYQA, :LN_SBPLX, :LN_NEWUOA
Expand All @@ -19,8 +20,8 @@ function get_right_endpoint(
max_iter::Int = 10^5,
scan_grad::Union{Function, Symbol} = :EMPTY,
loss_grad::Union{Function, Symbol} = :EMPTY,
kwargs...
)
#kwargs...
)
# dim of the theta vector
n_theta = length(theta_init)

Expand All @@ -45,7 +46,8 @@ function get_right_endpoint(

# optimizer
local_opt = Opt(local_alg, n_theta)
ftol_abs!(local_opt, scan_tol) #ftol_abs
ftol_abs!(local_opt, scan_tol)
ftol_rel!(local_opt, scan_rtol)
# local_opt.initial_step = fill(1., n_theta) # changes fitting but still unstable

# flags to analyze fitting stop
Expand Down Expand Up @@ -108,7 +110,7 @@ function get_right_endpoint(
inequality_constraint!(
opt,
constraints_func,
loss_tol
1e-3 # XXX: magic number, loss_tol
)

# version 1: internal :LN_AUGLAG box constrains
Expand Down Expand Up @@ -166,10 +168,13 @@ function get_right_endpoint(
),
scan_bound::Float64 = 9.0,
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3,
scan_rtol::Float64 = 0.,
loss_tol::Float64 = 0.,
local_alg::Symbol = :LN_NELDERMEAD,
kwargs... # for get_right_endpoint
)
max_iter::Int = 10^5,
loss_grad::Union{Function, Symbol} = :EMPTY,
#kwargs...
)
# checking arguments
if theta_num > length(theta_init)
throw(DomainError(theta_num, "theta_num exceed theta dimention"))
Expand All @@ -188,13 +193,16 @@ function get_right_endpoint(
loss_func,
method;

theta_bounds = theta_bounds,
scan_bound = scan_bound,
scan_tol = scan_tol,
loss_tol = loss_tol,
local_alg = local_alg,
scan_grad = scan_grad,
kwargs...
theta_bounds,
scan_bound,
scan_tol,
scan_rtol,
loss_tol,
local_alg,
max_iter,
scan_grad,
loss_grad
#kwargs...
)
end

Expand Down
32 changes: 19 additions & 13 deletions src/get_endpoint.jl
Expand Up @@ -120,8 +120,7 @@ function get_endpoint(
direction::Symbol = :right;

loss_crit::Float64 = 0.0,
# :direct, :lin, :log, :logit
scale::Vector{Symbol} = fill(:direct, length(theta_init)),
scale::Vector{Symbol} = fill(:direct, length(theta_init)), # :direct, :lin, :log, :logit
theta_bounds::Vector{Tuple{Float64,Float64}} = unscaling.(
fill((-Inf, Inf), length(theta_init)),
scale
Expand All @@ -131,12 +130,13 @@ function get_endpoint(
scale[theta_num]
),
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3,
loss_tol::Float64 = 0.,
local_alg::Symbol = :LN_NELDERMEAD,
max_iter::Int = 10^5,
loss_grad::Union{Function, Symbol} = :EMPTY,
silent::Bool = false,
kwargs... # other options for get_right_endpoint
)
#kwargs... # other options for get_right_endpoint
)
isLeft = direction == :left
n_theta = length(theta_init)

Expand Down Expand Up @@ -247,10 +247,12 @@ function get_endpoint(
theta_bounds = theta_bounds_gd,
scan_bound = scan_bound_gd,
scan_tol = scan_tol,
loss_tol = loss_tol,
local_alg = local_alg,
loss_grad = loss_grad_gd,
kwargs...
#scan_rtol
loss_tol,
local_alg,
max_iter,
loss_grad = loss_grad_gd
#kwargs...
)

# transforming back
Expand Down Expand Up @@ -334,13 +336,14 @@ function get_endpoint(
),
scan_bound::Float64 = (direction==:left) ? -1e9 : 1e9, # log scan bound is not implemented
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3,
loss_tol::Float64 = 0.,
local_alg::Symbol = :LN_NELDERMEAD,
max_iter::Int = 10^5,
scan_grad::Union{Function, Symbol} = :EMPTY,
loss_grad::Union{Function, Symbol} = :EMPTY,
silent::Bool = false,
kwargs... # other options for get_right_endpoint
)
#kwargs... # other options for get_right_endpoint
)
isLeft = direction == :left
n_theta = length(theta_init)
loss_init = loss_func(theta_init)
Expand Down Expand Up @@ -466,14 +469,17 @@ function get_endpoint(
scan_func_gd,
loss_func_gd,
Val(method);

theta_bounds = theta_bounds_gd,
scan_bound = scan_bound_gd,
scan_tol,
# scan_rtol, # not required
loss_tol,
local_alg,
max_iter,
scan_grad = scan_grad_gd,
loss_grad = loss_grad_gd,
kwargs...
#kwargs...
)

# transforming back
Expand Down
69 changes: 21 additions & 48 deletions src/get_interval.jl
Expand Up @@ -11,7 +11,7 @@
scan_tol::Float64 # fitting tolerance for local optimizer (default - `1e-3`)
loss_tol::Float64 # constraints tolerance
local_alg::Symbol # local fitting algorithm (default - `:LN_NELDERMEAD`)
fitter_options::Any
options::Any
end
Structure storing input data for parameter identification
Expand All @@ -21,14 +21,16 @@ struct ParamIntervalInput
theta_num::Int # number of the parameter for analysis
scan_func::Function
loss_func::Function # loss function
loss_crit::Float64 # loss function maximum value, "identifiability level"
method::Symbol
scale::Vector{Symbol}
theta_bounds::Vector{Tuple{Float64, Float64}} # search bounds for id parameter
#loss_crit::Float64 # loss function maximum value, "identifiability level"
#scale::Vector{Symbol}
#theta_bounds::Vector{Tuple{Float64, Float64}} # search bounds for id parameter
scan_bounds::Tuple{Float64,Float64}
scan_tol::Float64 # fitting tolerance for local optimizer (default - 1e-3)
loss_tol::Float64 # constraints tolerance
local_alg::Symbol # local fitting algorithm (default - :LN_NELDERMEAD)
fitter_options::Any
#scan_tol::Float64 # fitting tolerance for local optimizer (default - 1e-3)
#loss_tol::Float64 # constraints tolerance
#local_alg::Symbol # local fitting algorithm (default - :LN_NELDERMEAD)
options::Any
end

"""
Expand Down Expand Up @@ -100,50 +102,34 @@ function get_interval(
loss_func::Function,
method::Symbol;

loss_crit::Float64 = 0.0,
scale::Vector{Symbol} = fill(:direct, length(theta_init)),
theta_bounds::Vector{Tuple{Float64,Float64}} = unscaling.(
fill((-Inf, Inf), length(theta_init)),
scale
),
scan_bounds::Tuple{Float64,Float64} = unscaling.(
(-9.0, 9.0),
scale[theta_num]
),
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3,
local_alg::Symbol = :LN_NELDERMEAD,
kwargs... # other options for get_right_endpoint
)
)
# both endpoints
endpoints = [get_endpoint(
theta_init,
theta_num,
loss_func,
method,
[:left,:right][i]; # method
loss_crit = loss_crit,
scale = scale,
theta_bounds = theta_bounds,

scale,
scan_bound = scan_bounds[i],
scan_tol = scan_tol,
loss_tol = loss_tol,
local_alg = local_alg,
kwargs... # options for local fitter
) for i in 1:2]

input = ParamIntervalInput(
theta_init,
theta_num,
(x)->x[theta_num],
(x) -> x[theta_num],
loss_func,
loss_crit,
method,
scale,
theta_bounds,
scan_bounds,
scan_tol,
loss_tol,
local_alg,
kwargs
)

Expand Down Expand Up @@ -207,32 +193,23 @@ function get_interval(
loss_func::Function,
method::Symbol;

loss_crit::Float64 = 0.0,
scale::Vector{Symbol} = fill(:direct, length(theta_init)),
theta_bounds::Vector{Tuple{Float64,Float64}} = unscaling.(
fill((-Inf, Inf), length(theta_init)),
scale
scan_bounds::Tuple{Float64,Float64} = unscaling.(
(-9.0, 9.0),
scale[theta_num]
),
scan_bounds::Tuple{Float64,Float64} = (-1e9, 1e9), # log scan bound is not implemented
scan_tol::Float64 = 1e-3,
loss_tol::Float64 = 1e-3,
local_alg::Symbol = :LN_NELDERMEAD,
kwargs... # other options for get_right_endpoint
)
)
# both endpoints
endpoints = [get_endpoint(
theta_init,
scan_func,
loss_func,
method,
[:left,:right][i]; # method
loss_crit = loss_crit,
scale = scale,
theta_bounds = theta_bounds,

scale,
scan_bound = scan_bounds[i],
scan_tol = scan_tol,
loss_tol = loss_tol,
local_alg = local_alg,
kwargs...
) for i in 1:2]

Expand All @@ -241,13 +218,9 @@ function get_interval(
0,
scan_func,
loss_func,
loss_crit,
method,
scale,
theta_bounds,
scan_bounds,
scan_tol,
loss_tol,
local_alg,
kwargs
)

Expand Down
20 changes: 11 additions & 9 deletions src/plot_interval.jl
Expand Up @@ -31,16 +31,18 @@ profile points and make your plot more smooth
label --> "Identifiability level"
seriestype --> :hline
line := (2.5, :purple)
[pi.input.loss_crit]
[pi.input.options[:loss_crit]]
end

if (pi.result[1].value != nothing) || (pi.result[2].value != nothing)
if !isa(pi.result[1].value, Nothing) || !isa(pi.result[2].value, Nothing)
@series begin
label --> "Identifiability inteval"
seriestype --> :vline
line := (2.1, :pink)
[pi.result[1].value != nothing ? pi.result[1].value : NaN,
pi.result[2].value != nothing ? pi.result[2].value : NaN]
[
!isa(pi.result[1].value, Nothing) ? pi.result[1].value : NaN,
!isa(pi.result[2].value, Nothing) ? pi.result[2].value : NaN
]

#[pi.result[1].value,pi.result[2].value]
end
Expand Down Expand Up @@ -109,7 +111,7 @@ See `PlotUtils.adapted_grid`.
function update_profile_points!(
pi::ParamInterval;
max_recursions::Int = 2
)
)
for ep in pi.result
if ep.status != :SCAN_BOUND_REACHED
ep_start = pi.input.theta_init[pi.input.theta_num]
Expand All @@ -121,10 +123,10 @@ function update_profile_points!(
pi.input.theta_init,
pi.input.theta_num,
pi.input.loss_func,
pi.input.local_alg,
pi.input.theta_bounds,
pi.input.loss_tol;
max_recursions = max_recursions
pi.input.options[:local_alg],
pi.input.options[:theta_bounds],
pi.input.options[:loss_tol];
max_recursions
)
else
@info "$(string(ep.direction)) - a half-open interval"
Expand Down
6 changes: 4 additions & 2 deletions test/test_plots.jl
Expand Up @@ -2,12 +2,14 @@ using Plots
# plotly()

@testset "plot with no errors" begin
method = :LIN_EXTRAPOL
res0 = [get_interval(
[3., 2., 2.1],
i,
f_3p_1im_dep,
method;
:LIN_EXTRAPOL;
local_alg = :LN_NELDERMEAD,
theta_bounds = [(-12., 12.), (-12., 12.), (-12., 12.)],
loss_tol = 1e-3,
loss_crit = 9.,
silent = true
) for i in 1:3]
Expand Down

0 comments on commit f63e109

Please sign in to comment.