diff --git a/src/interface.jl b/src/interface.jl index 61c0388..25d89c7 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -70,7 +70,7 @@ end # Getters are without ! and accept only an objective and index or just an objective value(obj::AbstractObjective) = obj.F gradient(obj::AbstractObjective) = obj.DF -jacobian(obj::AbstractObjective) = gradient(obj) +jacobian(obj::AbstractObjective) = obj.DF gradient(obj::AbstractObjective, i::Integer) = obj.DF[i] hessian(obj::AbstractObjective) = obj.H @@ -103,6 +103,16 @@ function jacobian!!(obj, x) copy!(obj.x_df, x) obj.df_calls .+= 1 end +function jacobian(obj::AbstractObjective, x) + if x != obj.x_df + tmp = copy(obj.DF) + jacobian!!(obj, x) + newdf = copy(obj.DF) + copy!(obj.DF, tmp) + return newdf + end + obj.DF +end value!!(obj::NonDifferentiable{TF, TX, Tcplx}, x) where {TF<:AbstractArray, TX, Tcplx} = value!!(obj, obj.F, x) value!!(obj::OnceDifferentiable{TF, TDF, TX, Tcplx}, x) where {TF<:AbstractArray, TDF, TX, Tcplx} = value!!(obj, obj.F, x) diff --git a/src/objective_types/incomplete.jl b/src/objective_types/incomplete.jl index 4705c75..ba515a3 100644 --- a/src/objective_types/incomplete.jl +++ b/src/objective_types/incomplete.jl @@ -74,3 +74,10 @@ function OnceDifferentiable(t::Union{InplaceObjective, NotInplaceObjective}, x:: fdf = make_fdf(t, x, F) OnceDifferentiable(f, df, fdf, x, F) end + +function OnceDifferentiable(t::Union{InplaceObjective, NotInplaceObjective}, x::AbstractArray, F::AbstractArray) + f = make_f(t, x, F) + df = make_df(t, x, F) + fdf = make_fdf(t, x, F) + OnceDifferentiable(f, df, fdf, x, F) +end diff --git a/test/incomplete.jl b/test/incomplete.jl index 5f2ccb1..c249c4b 100644 --- a/test/incomplete.jl +++ b/test/incomplete.jl @@ -68,4 +68,80 @@ @test gradient(OD) == g(2.*x) end +end +@testset "incomplete objectives vectors" begin + import NLSolversBase: df, fdf, make_f, make_df, make_fdf + function tf(x) + x.^2 + end + function tf(F, x) + copy!(F, tf(x)) + end + + tj!(J, x) = copy!(J, diagm(x)) + tj(x) = diagm(x) + + function tfj!(F, J, x) + copy!(J, diagm(x)) + copy!(F, tf(x)) + end + function just_tfj!(F, J, x) + !(J == nothing) && copy!(J, diagm(x)) + !(F == nothing) && copy!(F, tf(x)) + end + tfj(x) = tf(x), tj(x) + + fdf!_real = only_fj!(just_tfj!) + fdf_real = only_fj(tfj) + + df_fdf_real = only_j_and_fj(tj, tfj) + srand(3259) + x = rand(10) + J_cache = similar(diagm(x)) + J_cache2 = similar(diagm(x)) + F_cache = similar(x) + F_cache2 = similar(x) + + @test df(fdf!_real) === nothing + @test df(fdf_real) === nothing + @test df(df_fdf_real) === tj + @test df(df_fdf_real)(x) == tj(x) + + @test fdf(fdf!_real) === just_tfj! + @test fdf(fdf_real) === tfj + @test df(df_fdf_real) == tj + @test fdf(df_fdf_real) == tfj + @test df(df_fdf_real)(x) == tj(x) + @test fdf(df_fdf_real)(x) == tfj(x) + + for FDF in (fdf_real, fdf!_real) + @test make_f(FDF, x, x)(F_cache, x) == tf(x) + make_df(FDF, x, x)(J_cache, x) + tj!(J_cache2, x) + @test J_cache == J_cache2 + make_fdf(FDF, x, x)(F_cache, J_cache, x.*2) + tfj!(F_cache2, J_cache2, x.*2) + @test F_cache == F_cache2 + @test J_cache == J_cache2 + end + + nd_fj = NonDifferentiable(only_fj(tfj), x, x) + nd_fj! = NonDifferentiable(only_fj!(just_tfj!), x, x) + for ND in (nd_fj, nd_fj!) + value!(ND, x) + value(ND) == tf(x) + end + od_fj = OnceDifferentiable(only_fj(tfj), x, x) + od_fj! = OnceDifferentiable(only_fj!(just_tfj!), x, x) + for OD in (od_fj, od_fj!) + value!(OD, x) + @test value(OD) == tf(x) + jacobian!(OD, x) + @test jacobian(OD) == tj(x) + @test jacobian(OD, x) == tj(x) + value_jacobian!(OD, 2.*x) + @test value(OD) == tf(2.*x) + @test jacobian(OD) == tj(2.*x) + end + end \ No newline at end of file