Skip to content

Commit

Permalink
Merge pull request #1 from JuliaNLSolvers/pkm/refactor
Browse files Browse the repository at this point in the history
Extract code from Optim.
  • Loading branch information
pkofod authored Mar 17, 2017
2 parents 4ad12ce + e8f9375 commit 7e5bd03
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 1 deletion.
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
julia 0.5
Compat 0.18.0
18 changes: 17 additions & 1 deletion src/NLSolversBase.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
module NLSolversBase

# package code goes here
using Compat

import Base: gradient
export NonDifferentiable,
OnceDifferentiable,
TwiceDifferentiable,
AbstractObjective,
value,
value!,
value_gradient!,
gradient,
gradient!,
hessian,
hessian!

include("objective_types.jl")
include("interface.jl")

end # module
61 changes: 61 additions & 0 deletions src/interface.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
function _unchecked_value!(obj, x)
obj.f_calls .+= 1
copy!(obj.last_x_f, x)
obj.f_x = obj.f(x)
end
function value(obj, x)
if x != obj.last_x_f
obj.f_calls += 1
return obj.f(x)
end
obj.f_x
end
function value!(obj, x)
if x != obj.last_x_f
_unchecked_value!(obj, x)
end
obj.f_x
end


function _unchecked_gradient!(obj, x)
obj.g_calls .+= 1
copy!(obj.last_x_g, x)
obj.g!(x, obj.g)
end
function gradient!(obj::AbstractObjective, x)
if x != obj.last_x_g
_unchecked_gradient!(obj, x)
end
end

function value_gradient!(obj::AbstractObjective, x)
if x != obj.last_x_f && x != obj.last_x_g
obj.f_calls .+= 1
obj.g_calls .+= 1
obj.last_x_f[:], obj.last_x_g[:] = copy(x), copy(x)
obj.f_x = obj.fg!(x, obj.g)
elseif x != obj.last_x_f
_unchecked_value!(obj, x)
elseif x != obj.last_x_g
_unchecked_gradient!(obj, x)
end
obj.f_x
end

function _unchecked_hessian!(obj::AbstractObjective, x)
obj.h_calls .+= 1
copy!(obj.last_x_h, x)
obj.h!(x, obj.H)
end
function hessian!(obj::AbstractObjective, x)
if x != obj.last_x_h
_unchecked_hessian!(obj, x)
end
end

# Getters are without ! and accept only an objective and index or just an objective
value(obj::AbstractObjective) = obj.f_x
gradient(obj::AbstractObjective) = obj.g
gradient(obj::AbstractObjective, i::Integer) = obj.g[i]
hessian(obj::AbstractObjective) = obj.H
79 changes: 79 additions & 0 deletions src/objective_types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@compat abstract type AbstractObjective end

# Used for objectives and solvers where no gradient is available/exists
type NonDifferentiable{T} <: AbstractObjective
f
f_x::T
last_x_f::Array{T}
f_calls::Vector{Int}
end
# The user friendly/short form NonDifferentiable constructor
NonDifferentiable{T}(f, x_seed::Array{T}) = NonDifferentiable(f, f(x_seed), copy(x_seed), [1])

# Used for objectives and solvers where the gradient is available/exists
type OnceDifferentiable{T, Tgrad} <: AbstractObjective
f
g!
fg!
f_x::T
g::Tgrad
last_x_f::Array{T}
last_x_g::Array{T}
f_calls::Vector{Int}
g_calls::Vector{Int}
end
# The user friendly/short form OnceDifferentiable constructor
function OnceDifferentiable(f, g!, fg!, x_seed)
g = similar(x_seed)
g!(x_seed, g)
OnceDifferentiable(f, g!, fg!, f(x_seed), g, copy(x_seed), copy(x_seed), [1], [1])
end

# Automatically create the fg! helper function if only f and g! is provided
function OnceDifferentiable(f, g!, x_seed)
function fg!(x, storage)
g!(x, storage)
return f(x)
end
return OnceDifferentiable(f, g!, fg!, x_seed)
end

# Used for objectives and solvers where the gradient and Hessian is available/exists
type TwiceDifferentiable{T<:Real} <: AbstractObjective
f
g!
fg!
h!
f_x::T
g::Vector{T}
H::Matrix{T}
last_x_f::Vector{T}
last_x_g::Vector{T}
last_x_h::Vector{T}
f_calls::Vector{Int}
g_calls::Vector{Int}
h_calls::Vector{Int}
end
# The user friendly/short form TwiceDifferentiable constructor
function TwiceDifferentiable{T}(f, g!, fg!, h!, x_seed::Array{T})
n_x = length(x_seed)
g = similar(x_seed)
H = Array{T}(n_x, n_x)
g!(x_seed, g)
h!(x_seed, H)
TwiceDifferentiable(f, g!, fg!, h!, f(x_seed),
g, H, copy(x_seed),
copy(x_seed), copy(x_seed), [1], [1], [1])
end

# Automatically create the fg! helper function if only f, g! and h! is provided
function TwiceDifferentiable{T}(f,
g!,
h!,
x_seed::Array{T})
function fg!(x::Vector, storage::Vector)
g!(x, storage)
return f(x)
end
return TwiceDifferentiable(f, g!, fg!, h!, x_seed)
end

0 comments on commit 7e5bd03

Please sign in to comment.