Skip to content

Commit

Permalink
version 0.2.4 with improved performance: parametric types/_domain_check
Browse files Browse the repository at this point in the history
  • Loading branch information
tmigot committed Oct 31, 2020
1 parent f8b23e4 commit ee2d482
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 137 deletions.
36 changes: 21 additions & 15 deletions src/State/GenericStatemod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ GenericState(x, current\\_score = 1.0)
See also: Stopping, NLPAtX
"""
mutable struct GenericState <: AbstractState
mutable struct GenericState{T<:Union{AbstractFloat,AbstractVector}} <: AbstractState

x :: AbstractVector
x :: T

d :: Iterate
res :: Iterate
d :: Union{T,eltype(T),Nothing}
res :: Union{T,eltype(T),Nothing}

#Current time
current_time :: FloatVoid
current_time :: Union{eltype(T),Nothing}
#Current score
current_score :: Iterate
current_score :: Union{T,eltype(T),Nothing}

function GenericState(x :: AbstractVector;
d :: Iterate = nothing,
res :: Iterate = nothing,
current_time :: FloatVoid = nothing,
current_score :: Iterate = nothing)
function GenericState(x :: T;
d :: Union{T,eltype(T),Nothing} = nothing,
res :: Union{T,eltype(T),Nothing} = nothing,
current_time :: Union{eltype(T),Nothing} = nothing,
current_score :: Union{T,eltype(T),Nothing} = nothing) where T <:Union{AbstractFloat,AbstractVector}

return new(x, d, res, current_time, current_score)
return new{T}(x, d, res, current_time, current_score)
end
end

Expand All @@ -63,7 +63,7 @@ update!(state1, convert = true, current\\_time = 2.0)
See also: GenericState, reinit!, update\\_and\\_start!, update\\_and\\_stop!
"""
function update!(stateatx :: AbstractState; convert = false, kwargs...)
function update!(stateatx :: AbstractState; convert :: Bool = false, kwargs...)

kwargs = Dict(kwargs)

Expand Down Expand Up @@ -96,7 +96,7 @@ Examples:
reinit!(state2)
reinit!(state2, current_time = 1.0)
"""
function reinit!(stateatx :: AbstractState, x :: Iterate; kwargs...)
function reinit!(stateatx :: AbstractState, x :: Union{Number, AbstractVector}; kwargs...)

for k fieldnames(typeof(stateatx))
if k != :x setfield!(stateatx, k, nothing) end
Expand All @@ -121,12 +121,18 @@ function _domain_check(stateatx :: AbstractState)
domainerror = false

for k fieldnames(typeof(stateatx))
try domainerror = domainerror || (true in isnan.(getfield(stateatx, k))) catch end
_temp = getfield(stateatx, k)
domainerror = domainerror || _check_nan(_temp)
end

return domainerror
end

_check_nan(field :: Any) = false #Nothing or Counters
_check_nan(field :: SparseMatrixCSC) = any(isnan, field.nzval) #because checking in sparse matrices is too slow
_check_nan(field :: Union{AbstractVector,AbstractMatrix}) = any(isnan, field)
_check_nan(field :: AbstractFloat) = isnan(field)

import Base.copy
ex=:(_genobj(typ)=$(Expr(:new, :typ))); eval(ex)
function copy(state :: AbstractState)
Expand Down
32 changes: 16 additions & 16 deletions src/State/NLPAtXmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,32 @@ Note:
See also: GenericState, update!, update\\_and\\_start!, update\\_and\\_stop!, reinit!
"""
mutable struct NLPAtX <: AbstractState
mutable struct NLPAtX{T <: AbstractVector} <: AbstractState

#Unconstrained State
x :: AbstractVector # current point
fx :: FloatVoid # objective function
gx :: Iterate # gradient size: x
x :: T # current point
fx :: Union{eltype(T),Nothing} # objective function
gx :: Union{T,eltype(T),Nothing} # gradient size: x
Hx :: MatrixType # hessian size: |x| x |x|

#Bounds State
mu :: Iterate # Lagrange multipliers with bounds size of |x|
mu :: Union{T,eltype(T),Nothing} # Lagrange multipliers with bounds size of |x|

#Constrained State
cx :: Iterate # vector of constraints lc <= c(x) <= uc
cx :: Union{T,eltype(T),Nothing} # vector of constraints lc <= c(x) <= uc
Jx :: MatrixType # jacobian matrix, size: |lambda| x |x|
lambda :: AbstractVector # Lagrange multipliers
lambda :: T # Lagrange multipliers

d :: Iterate #search direction
res :: Iterate #residual
d :: Union{T,eltype(T),Nothing} #search direction
res :: Union{T,eltype(T),Nothing} #residual

#Resources State
current_time :: FloatVoid
current_score :: Iterate
current_time :: Union{eltype(T),Nothing}
current_score :: Union{T,eltype(T),Nothing}
evals :: Counters

function NLPAtX(x :: AbstractVector,
lambda :: AbstractVector;
function NLPAtX(x :: T,
lambda :: T;
fx :: FloatVoid = nothing,
gx :: Iterate = nothing,
Hx :: MatrixType = nothing,
Expand All @@ -77,11 +77,11 @@ mutable struct NLPAtX <: AbstractState
res :: Iterate = nothing,
current_time :: FloatVoid = nothing,
current_score :: Iterate = nothing,
evals :: Counters = Counters())
evals :: Counters = Counters()) where T <: AbstractVector

_size_check(x, lambda, fx, gx, Hx, mu, cx, Jx)

return new(x, fx, gx, Hx, mu, cx, Jx, lambda, d, res, current_time, current_score, evals)
return new{T}(x, fx, gx, Hx, mu, cx, Jx, lambda, d, res, current_time, current_score, evals)
end
end

Expand Down Expand Up @@ -114,7 +114,7 @@ prioritized over the existing *x*, *lambda* and the default *Counters*.
function reinit!(stateatx :: NLPAtX, x :: AbstractVector, l :: AbstractVector; kwargs...)

for k fieldnames(typeof(stateatx))
if !(k [:x,:lambda,:evals]) setfield!(stateatx, k, nothing) end
if k [:x,:lambda,:evals] setfield!(stateatx, k, nothing) end
end

return update!(stateatx; x=x, lambda = l, evals = Counters(), kwargs...)
Expand Down
2 changes: 1 addition & 1 deletion src/Stopping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ the Stopping to reuse for another call.
"""
module Stopping

using LinearAlgebra, LinearOperators, DataFrames, NLPModels
using LinearAlgebra, LinearOperators, SparseArrays, DataFrames, NLPModels

const Iterate = Union{Number, AbstractVector, Nothing}
const FloatVoid = Union{Number, Nothing}
Expand Down
68 changes: 34 additions & 34 deletions src/Stopping/GenericStoppingmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,61 +38,61 @@
There is an additional default constructor which creates a Stopping with a default State.
`GenericStopping(:: Any, :: Iterate; kwargs...)`
`GenericStopping(:: Any, :: Union{Number, AbstractVector}; kwargs...)`
Note: Keywords arguments are forwarded to the classical constructor.
Examples:
GenericStopping(pb, x0, rtol = 1e-1)
"""
mutable struct GenericStopping <: AbstractStopping
mutable struct GenericStopping{T <: AbstractState} <: AbstractStopping

# Problem
pb :: Any
pb :: Any

# Problem stopping criterion
meta :: AbstractStoppingMeta
meta :: AbstractStoppingMeta

# Current information on the problem
current_state :: AbstractState
current_state :: T

# Stopping of the main problem, or nothing
main_stp :: Union{AbstractStopping, Nothing}
main_stp :: Union{AbstractStopping, Nothing}

# History of states
listofstates :: Union{ListStates, Nothing}
listofstates :: Union{ListStates, Nothing}

# User-specific structure
user_specific_struct :: Any

function GenericStopping(pb :: Any,
current_state :: AbstractState;
current_state :: T;
meta :: AbstractStoppingMeta = StoppingMeta(),
main_stp :: Union{AbstractStopping, Nothing} = nothing,
list :: Union{ListStates, Nothing} = nothing,
user_specific_struct :: Any = nothing,
kwargs...)
kwargs...) where T<:AbstractState

if !(isempty(kwargs))
meta = StoppingMeta(; kwargs...)
end

return new(pb, meta, current_state, main_stp, list, user_specific_struct)
return new{T}(pb, meta, current_state, main_stp, list, user_specific_struct)
end
end

function GenericStopping(pb :: Any, x :: Iterate; kwargs...)
function GenericStopping(pb :: Any, x :: Union{Number, AbstractVector}; kwargs...)
return GenericStopping(pb, GenericState(x); kwargs...)
end

"""
fill_in!: fill in the unspecified values of the AbstractState.
`fill_in!(:: AbstractStopping, x :: Iterate)`
`fill_in!(:: AbstractStopping, x :: Union{Number, AbstractVector})`
Note: NotImplemented for Abstract/Generic-Stopping.
"""
function fill_in!(stp :: AbstractStopping, x :: Iterate)
function fill_in!(stp :: AbstractStopping, x :: Union{Number, AbstractVector})
return throw(error("NotImplemented function"))
end

Expand Down Expand Up @@ -138,15 +138,15 @@ function start!(stp :: AbstractStopping; no_start_opt_check :: Bool = false, kwa
end
#and synchornize with the State
if stt_at_x.current_time == nothing
update!(stt_at_x, current_time = time())
update!(stt_at_x, current_time = time())
end

stp.meta.domainerror = _domain_check(stp.current_state)
if !stp.meta.domainerror && !no_start_opt_check
# Optimality check
optimality0 = _optimality_check(stp; kwargs...)
stp.meta.optimality0 = norm(optimality0, Inf)
if (true in isnan.(optimality0))
if (true in isnan.(optimality0))
stp.meta.domainerror = true
end

Expand Down Expand Up @@ -246,7 +246,7 @@ function stop!(stp :: AbstractStopping; kwargs...)
x = stp.current_state.x
time = stp.meta.start_time

stp.meta.domainerror = _domain_check(stp.current_state)
stp.meta.domainerror = _domain_check(stp.current_state) #pb here?
if !stp.meta.domainerror
# Optimality check
score = _optimality_check(stp; kwargs...)
Expand Down Expand Up @@ -305,12 +305,12 @@ end
\\_iteration\\_check!: check if the optimization algorithm has reached the iteration
limit.
`_iteration_check!(:: AbstractStopping, :: Iterate)`
`_iteration_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: Compare *meta.iteration_limit* with *meta.nb\\_of\\_stop*.
"""
function _iteration_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

max_iter = stp.meta.nb_of_stop >= stp.meta.max_iter

Expand All @@ -322,12 +322,12 @@ end
"""
\\_stalled\\_check!: check if the optimization algorithm is stalling.
`_stalled_check!(:: AbstractStopping, :: Iterate)`
`_stalled_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: By default *meta.stalled* is false for Abstract/Generic Stopping.
"""
function _stalled_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

stp.meta.stalled = false

Expand All @@ -337,14 +337,14 @@ end
"""
\\_tired\\_check!: check if the optimization algorithm has been running for too long.
`_tired_check!(:: AbstractStopping, :: Iterate; time_t :: Number = NaN)`
`_tired_check!(:: AbstractStopping, :: Union{Number, AbstractVector}; time_t :: Number = NaN)`
Note: - Return false if *time_t* is NaN (by default).
- Update *meta.tired*.
"""
function _tired_check!(stp :: AbstractStopping,
x :: Iterate;
time_t :: Number = NaN)
x :: T;
time_t :: Number = NaN) where T <: Union{Number, AbstractVector}

# Time check
if !isnan(time_t)
Expand All @@ -363,12 +363,12 @@ end
"""
\\_resources\\_check!: check if the optimization algorithm has exhausted the resources.
`_resources_check!(:: AbstractStopping, :: Iterate)`
`_resources_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: By default *meta.resources* is false for Abstract/Generic Stopping.
"""
function _resources_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

max_evals = false
max_f = false
Expand All @@ -381,13 +381,13 @@ end
"""
\\_main\\_pb\\_check!: check the resources and the time of the upper problem (if main_stp != nothing).
`_main_pb_check!(:: AbstractStopping, :: Iterate)`
`_main_pb_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: - Modify the meta of the *main_stp*.
- By default `meta.main_pb = false`.
"""
function _main_pb_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

# Time check
time = stp.main_stp.meta.start_time
Expand All @@ -413,12 +413,12 @@ end
"""
\\_unbounded\\_check!: check if x gets too big.
`_unbounded_check!(:: AbstractStopping, :: Iterate)`
`_unbounded_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: compare ||x|| with *meta.unbounded_x* and update *meta.unbounded*.
"""
function _unbounded_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

pnorm = stp.meta.norm_unbounded_x
x_too_large = norm(x, pnorm) >= stp.meta.unbounded_x
Expand All @@ -431,12 +431,12 @@ end
"""
\\_unbounded\\_problem!: check if problem relative informations are unbounded
`_unbounded_problem_check!(:: AbstractStopping, :: Iterate)`
`_unbounded_problem_check!(:: AbstractStopping, :: Union{Number, AbstractVector})`
Note: *meta.unbounded_pb* is false by default.
"""
function _unbounded_problem_check!(stp :: AbstractStopping,
x :: Iterate)
x :: T) where T <: Union{Number, AbstractVector}

stp.meta.unbounded_pb = false

Expand Down Expand Up @@ -469,7 +469,7 @@ Note:
and `meta.tol_check_neg(meta.atol, meta.rtol, meta.optimality0)`.
- Compatible size is not verified.
"""
function _null_test(stp :: AbstractStopping, optimality :: Union{Number,AbstractVector})
function _null_test(stp :: AbstractStopping, optimality :: T) where T <: Union{Number,AbstractVector}

atol, rtol, opt0 = stp.meta.atol, stp.meta.rtol, stp.meta.optimality0
check_pos = stp.meta.tol_check(atol, rtol, opt0)
Expand All @@ -484,9 +484,9 @@ end
"""
\\_user\\_check: nothing by default.
`_user_check!( :: AbstractStopping, x :: Iterate)`
`_user_check!( :: AbstractStopping, x :: Union{Number, AbstractVector})`
"""
function _user_check!(stp :: AbstractStopping, x :: Iterate)
function _user_check!(stp :: AbstractStopping, x :: T) where T <: Union{Number, AbstractVector}
nothing
end

Expand Down
Loading

0 comments on commit ee2d482

Please sign in to comment.