From c6719c7cd48179f4a8f2a17cf491147efbc36785 Mon Sep 17 00:00:00 2001 From: "Geoffrey K. Adams" Date: Tue, 23 Feb 2016 19:00:17 -0500 Subject: [PATCH] Change all Array and Vector to AbstractArray and AbstractVector --- src/check_derivative.jl | 4 ++-- src/derivative.jl | 30 +++++++++++++++--------------- src/finite_difference.jl | 22 +++++++++++----------- test/check_derivative.jl | 6 ++++++ test/derivative.jl | 17 +++++++++++++++-- test/finite_difference.jl | 9 +++++++++ 6 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/check_derivative.jl b/src/check_derivative.jl index a3a47ed..6ce7bf6 100644 --- a/src/check_derivative.jl +++ b/src/check_derivative.jl @@ -3,7 +3,7 @@ function check_derivative(f::Function, g::Function, x::Number) return maximum(abs(g(x) - auto_g(x))) end -function check_gradient{T <: Number}(f::Function, g::Function, x::Vector{T}) +function check_gradient{T <: Number}(f::Function, g::Function, x::AbstractVector{T}) auto_g = gradient(f) return maximum(abs(g(x) - auto_g(x))) end @@ -13,7 +13,7 @@ function check_second_derivative(f::Function, h::Function, x::Number) return maximum(abs(h(x) - auto_h(x))) end -function check_hessian{T <: Number}(f::Function, h::Function, x::Vector{T}) +function check_hessian{T <: Number}(f::Function, h::Function, x::AbstractVector{T}) auto_h = hessian(f) return maximum(abs(h(x) - auto_h(x))) end diff --git a/src/derivative.jl b/src/derivative.jl index 4999486..2c7a0b5 100644 --- a/src/derivative.jl +++ b/src/derivative.jl @@ -2,19 +2,19 @@ function derivative(f::Function, ftype::Symbol, dtype::Symbol) if ftype == :scalar g(x::Number) = finite_difference(f, float(x), dtype) elseif ftype == :vector - g(x::Vector) = finite_difference(f, float(x), dtype) + g(x::AbstractVector) = finite_difference(f, float(x), dtype) else error("ftype must :scalar or :vector") end return g end -Compat.@compat derivative{T <: Number}(f::Function, x::Union{T, Vector{T}}, dtype::Symbol = :central) = finite_difference(f, float(x), dtype) +Compat.@compat derivative{T <: Number}(f::Function, x::Union{T, AbstractVector{T}}, dtype::Symbol = :central) = finite_difference(f, float(x), dtype) derivative(f::Function, dtype::Symbol = :central) = derivative(f, :scalar, dtype) -Compat.@compat gradient{T <: Number}(f::Function, x::Union{T, Vector{T}}, dtype::Symbol = :central) = finite_difference(f, float(x), dtype) +Compat.@compat gradient{T <: Number}(f::Function, x::Union{T, AbstractVector{T}}, dtype::Symbol = :central) = finite_difference(f, float(x), dtype) gradient(f::Function, dtype::Symbol = :central) = derivative(f, :vector, dtype) -Compat.@compat function Base.gradient{T <: Number}(f::Function, x::Union{T, Vector{T}}, dtype::Symbol = :central) +Compat.@compat function Base.gradient{T <: Number}(f::Function, x::Union{T, AbstractVector{T}}, dtype::Symbol = :central) Base.warn_once("The finite difference methods from Calculus.jl no longer extend Base.gradient and should be called as Calculus.gradient instead. This usage is deprecated.") Calculus.gradient(f,x,dtype) end @@ -26,11 +26,11 @@ end ctranspose(f::Function) = derivative(f) -function jacobian{T <: Number}(f::Function, x::Vector{T}, dtype::Symbol) +function jacobian{T <: Number}(f::Function, x::AbstractVector{T}, dtype::Symbol) finite_difference_jacobian(f, x, dtype) end function jacobian(f::Function, dtype::Symbol) - g(x::Vector) = finite_difference_jacobian(f, x, dtype) + g(x::AbstractVector) = finite_difference_jacobian(f, x, dtype) return g end jacobian(f::Function) = jacobian(f, :central) @@ -39,22 +39,22 @@ function second_derivative(f::Function, g::Function, ftype::Symbol, dtype::Symbo if ftype == :scalar h(x::Number) = finite_difference_hessian(f, g, x, dtype) elseif ftype == :vector - h(x::Vector) = finite_difference_hessian(f, g, x, dtype) + h(x::AbstractVector) = finite_difference_hessian(f, g, x, dtype) else error("ftype must :scalar or :vector") end return h end -Compat.@compat function second_derivative{T <: Number}(f::Function, g::Function, x::Union{T, Vector{T}}, dtype::Symbol) +Compat.@compat function second_derivative{T <: Number}(f::Function, g::Function, x::Union{T, AbstractVector{T}}, dtype::Symbol) finite_difference_hessian(f, g, x, dtype) end -Compat.@compat function hessian{T <: Number}(f::Function, g::Function, x::Union{T, Vector{T}}, dtype::Symbol) +Compat.@compat function hessian{T <: Number}(f::Function, g::Function, x::Union{T, AbstractVector{T}}, dtype::Symbol) finite_difference_hessian(f, g, x, dtype) end -Compat.@compat function second_derivative{T <: Number}(f::Function, g::Function, x::Union{T, Vector{T}}) +Compat.@compat function second_derivative{T <: Number}(f::Function, g::Function, x::Union{T, AbstractVector{T}}) finite_difference_hessian(f, g, x, :central) end -Compat.@compat function hessian{T <: Number}(f::Function, g::Function, x::Union{T, Vector{T}}) +Compat.@compat function hessian{T <: Number}(f::Function, g::Function, x::Union{T, AbstractVector{T}}) finite_difference_hessian(f, g, x, :central) end function second_derivative(f::Function, x::Number, dtype::Symbol) @@ -63,10 +63,10 @@ end function hessian(f::Function, x::Number, dtype::Symbol) finite_difference_hessian(f, derivative(f), x, dtype) end -function second_derivative{T <: Number}(f::Function, x::Vector{T}, dtype::Symbol) +function second_derivative{T <: Number}(f::Function, x::AbstractVector{T}, dtype::Symbol) finite_difference_hessian(f, gradient(f), x, dtype) end -function hessian{T <: Number}(f::Function, x::Vector{T}, dtype::Symbol) +function hessian{T <: Number}(f::Function, x::AbstractVector{T}, dtype::Symbol) finite_difference_hessian(f, gradient(f), x, dtype) end function second_derivative(f::Function, x::Number) @@ -75,10 +75,10 @@ end function hessian(f::Function, x::Number) finite_difference_hessian(f, derivative(f), x, :central) end -function second_derivative{T <: Number}(f::Function, x::Vector{T}) +function second_derivative{T <: Number}(f::Function, x::AbstractVector{T}) finite_difference_hessian(f, gradient(f), x, :central) end -function hessian{T <: Number}(f::Function, x::Vector{T}) +function hessian{T <: Number}(f::Function, x::AbstractVector{T}) finite_difference_hessian(f, gradient(f), x, :central) end second_derivative(f::Function, g::Function, dtype::Symbol) = second_derivative(f, g, :scalar, dtype) diff --git a/src/finite_difference.jl b/src/finite_difference.jl index 34a39e4..e1fd882 100644 --- a/src/finite_difference.jl +++ b/src/finite_difference.jl @@ -98,8 +98,8 @@ end ############################################################################## function finite_difference!{S <: Number, T <: Number}(f::Function, - x::Vector{S}, - g::Vector{T}, + x::AbstractVector{S}, + g::AbstractVector{T}, dtype::Symbol) # What is the dimension of x? n = length(x) @@ -136,7 +136,7 @@ function finite_difference!{S <: Number, T <: Number}(f::Function, return end function finite_difference{T <: Number}(f::Function, - x::Vector{T}, + x::AbstractVector{T}, dtype::Symbol = :central) # Allocate memory for gradient g = Array(Float64, length(x)) @@ -157,9 +157,9 @@ end function finite_difference_jacobian!{R <: Number, S <: Number, T <: Number}(f::Function, - x::Vector{R}, - f_x::Vector{S}, - J::Array{T}, + x::AbstractVector{R}, + f_x::AbstractVector{S}, + J::AbstractArray{T}, dtype::Symbol = :central) # What is the dimension of x? m, n = size(J) @@ -192,7 +192,7 @@ function finite_difference_jacobian!{R <: Number, return end function finite_difference_jacobian{T <: Number}(f::Function, - x::Vector{T}, + x::AbstractVector{T}, dtype::Symbol = :central) # Establish a baseline for f_x f_x = f(x) @@ -233,8 +233,8 @@ end function finite_difference_hessian!{S <: Number, T <: Number}(f::Function, - x::Vector{S}, - H::Array{T}) + x::AbstractVector{S}, + H::AbstractArray{T}) # What is the dimension of x? n = length(x) @@ -265,7 +265,7 @@ function finite_difference_hessian!{S <: Number, Base.LinAlg.copytri!(H,'U') end function finite_difference_hessian{T <: Number}(f::Function, - x::Vector{T}) + x::AbstractVector{T}) # What is the dimension of x? n = length(x) @@ -280,7 +280,7 @@ function finite_difference_hessian{T <: Number}(f::Function, end function finite_difference_hessian{T <: Number}(f::Function, g::Function, - x::Vector{T}, + x::AbstractVector{T}, dtype::Symbol = :central) finite_difference_jacobian(g, x, dtype) end diff --git a/test/check_derivative.jl b/test/check_derivative.jl index 2717bef..6511c15 100644 --- a/test/check_derivative.jl +++ b/test/check_derivative.jl @@ -21,3 +21,9 @@ @test check_hessian(x -> sin(x[1]) + cos(x[2]), x -> [-sin(x[1]) 0.0; 0.0 -cos(x[2])], [10.0, 10.0]) < 10e-4 @test check_hessian(x -> sin(x[1]) + cos(x[2]), x -> [-sin(x[1]) 0.0; 0.0 -cos(x[2])], [100.0, 100.0]) < 10e-4 @test check_hessian(x -> sin(x[1]) + cos(x[2]), x -> [-sin(x[1]) 0.0; 0.0 -cos(x[2])], [1000.0, 1000.0]) < 10e-4 + +# Test functionality for other AbstractArray types +@test check_gradient(x -> sin(x[1]) + cos(x[2]), x -> [cos(x[1]), -sin(x[2])], + sub([0.0, 0.0],:)) < 10e-4 +@test check_hessian(x -> sin(x[1]) + cos(x[2]), x -> [-sin(x[1]) 0.0; 0.0 -cos(x[2])], + sub([0.0, 0.0],:)) < 10e-4 diff --git a/test/derivative.jl b/test/derivative.jl index c482cc1..64be158 100644 --- a/test/derivative.jl +++ b/test/derivative.jl @@ -9,10 +9,14 @@ f1(x::Real) = sin(x) @test norm(derivative(f1, :central)(0.0) - cos(0.0)) < 10e-4 @test norm(derivative(f1)(0.0) - cos(0.0)) < 10e-4 -f2(x::Vector) = sin(x[1]) +f2(x::AbstractVector) = sin(x[1]) @test norm(derivative(f2, :vector, :forward)([0.0]) .- cos(0.0)) < 10e-4 @test norm(derivative(f2, :vector, :central)([0.0]) .- cos(0.0)) < 10e-4 +# Test functionality for SubArrays +@test norm(derivative(f2, :vector, :forward)(sub([0.0],:)) .- cos(0.0)) < 10e-4 +@test norm(derivative(f2, :vector, :central)(sub([0.0],:)) .- cos(0.0)) < 10e-4 + # # ctranspose overloading # @@ -26,11 +30,16 @@ end # gradient() # -f4(x::Vector) = (100.0 - x[1])^2 + (50.0 - x[2])^2 +f4(x::AbstractVector) = (100.0 - x[1])^2 + (50.0 - x[2])^2 @test norm(Calculus.gradient(f4, :forward)([100.0, 50.0]) - [0.0, 0.0]) < 10e-4 @test norm(Calculus.gradient(f4, :central)([100.0, 50.0]) - [0.0, 0.0]) < 10e-4 @test norm(Calculus.gradient(f4)([100.0, 50.0]) - [0.0, 0.0]) < 10e-4 +# Test for SubArrays +@test norm(Calculus.gradient(f4, :forward)(sub([100.0, 50.0],:)) - [0.0, 0.0]) < 10e-4 +@test norm(Calculus.gradient(f4, :central)(sub([100.0, 50.0],:)) - [0.0, 0.0]) < 10e-4 +@test norm(Calculus.gradient(f4)(sub([100.0, 50.0],:)) - [0.0, 0.0]) < 10e-4 + # # second_derivative() # @@ -47,3 +56,7 @@ f4(x::Vector) = (100.0 - x[1])^2 + (50.0 - x[2])^2 f5(x) = sin(x[1]) + cos(x[2]) @test norm(Calculus.gradient(f5)([0.0, 0.0]) - [cos(0.0), -sin(0.0)]) < 10e-4 @test norm(hessian(f5)([0.0, 0.0]) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 + +# And for SubArrays again +@test norm(Calculus.gradient(f5)(sub([0.0, 0.0],:)) - [cos(0.0), -sin(0.0)]) < 10e-4 +@test norm(hessian(f5)(sub([0.0, 0.0],:)) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 diff --git a/test/finite_difference.jl b/test/finite_difference.jl index e7a4a0f..fa2819c 100644 --- a/test/finite_difference.jl +++ b/test/finite_difference.jl @@ -30,6 +30,11 @@ @test norm(Calculus.finite_difference(x -> exp(-x[1]), [1.0], :central) - [-exp(-1.0)]) < 10e-4 @test norm(Calculus.finite_difference(x -> exp(-x[1]), [1.0]) - [-exp(-1.0)]) < 10e-4 +# Gradients of f when x is a SubArrays +@test norm(Calculus.finite_difference(x -> exp(-x[1]), sub([1.0],:), :forward) - [-exp(-1.0)]) < 10e-4 +@test norm(Calculus.finite_difference(x -> exp(-x[1]), sub([1.0],:), :central) - [-exp(-1.0)]) < 10e-4 +@test norm(Calculus.finite_difference(x -> exp(-x[1]), sub([1.0],:)) - [-exp(-1.0)]) < 10e-4 + # # Second derivatives of f: R -> R # @@ -52,6 +57,10 @@ gx = Calculus.gradient(fx) @test norm(Calculus.finite_difference_hessian(fx, gx, [0.0, 0.0], :central) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 @test norm(Calculus.finite_difference_hessian(fx, [0.0, 0.0]) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 +@test norm(gx(sub([0.0, 0.0],:)) - [cos(0.0), -sin(0.0)]) < 10e-4 +@test norm(Calculus.finite_difference_hessian(fx, gx, sub([0.0, 0.0],:), :central) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 +@test norm(Calculus.finite_difference_hessian(fx, sub([0.0, 0.0],:)) - [-sin(0.0) 0.0; 0.0 -cos(0.0)]) < 10e-4 + # # Taylor Series first derivatives #