State
As discussed before each Stopping contains a current_state <: AbstractState attribute containing the current information/state of the problem. When running the iterative loop, the State is updated and the Stopping make a decision based on this information.
The current_state contains all the information relative to a problem. We implemented three instances as an illustration:
GenericState;NLPAtXrepresenting the state of anNLPModel;OneDAtXfor 1D optimization problems.
GenericState is an illustration of the behavior of such object that minimally contains:
xthe current iterate;dthe current direction;resthe current residual;current_timethe current time;current_scorethe current optimality score.
By convention, x and current_score are mandatory information, and the other attribute are initialized with keywords arguments:
GenericState(zeros(n), 0.0, d = zeros(n), current_time = NaN)the alternative would be
GenericState(zeros(n), d = zeros(n), current_time = NaN)Beyond the use inside Stopping, returning the State also provides the user the opportunity to use some of the information computed by the algorithm.
FAQ: Are there Type constraints when initializing a State?
Yes, an AbstractState{S,T} is actually a paramtric type where S is the type of the current_score and T is the type of x.
x0, score0 = rand(n), Array{Float64,1}(undef, n)
GenericState(x0, score0) #is an AbstractState{Array{Float64,1}, Array{Float64,1}}By default, the current_score is a real number, hence
x0 = rand(n)
GenericState(x0) #is an AbstractState{Float64, Array{Float64,1}}These types can be obtained with the functions xtype and scoretype:
scoretype(stp.current_state)
xtype(stp.current_state)FAQ: Can I design a tailored State for my problem?
NLPAtX is an illustration of a more evolved instance associated to NLPModels for nonlinear optimization models. It contains:
mutable struct NLPAtX{S, T <: AbstractVector, MT <: AbstractMatrix} <: AbstractState{S, T}
#Unconstrained State
x :: T # current point
fx :: eltype(T) # objective function
gx :: T # gradient size: x
Hx :: MT # hessian size: |x| x |x|
#Bounds State
mu :: T # Lagrange multipliers with bounds size of |x|
#Constrained State
cx :: T # vector of constraints lc <= c(x) <= uc
Jx :: MT # jacobian matrix, size: |lambda| x |x|
lambda :: T # Lagrange multipliers
d :: T #search direction
res :: T #residual
#Resources State
current_time :: Float64
current_score :: S
evals :: Counters
function NLPAtX(x :: T,
lambda :: T,
current_score :: S;
fx :: eltype(T) = _init_field(eltype(T)),
gx :: T = _init_field(T),
Hx :: AbstractMatrix = _init_field(Matrix{eltype(T)}),
mu :: T = _init_field(T),
cx :: T = _init_field(T),
Jx :: AbstractMatrix = _init_field(Matrix{eltype(T)}),
d :: T = _init_field(T),
res :: T = _init_field(T),
current_time :: Float64 = NaN,
evals :: Counters = Counters()
) where {S, T <: AbstractVector}
_size_check(x, lambda, fx, gx, Hx, mu, cx, Jx)
return new{S, T, Matrix{eltype(T)}}(x, fx, gx, Hx, mu, cx, Jx, lambda, d,
res, current_time, current_score, evals)
end
end_init_field(T) initializes a value for a given type guaranteing type stability and minimal storage.