# Optimization.jl - Define the objective function and its gradient in the same function

**URL:** https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968
**Category:** Optimization (Mathematical)
**Tags:** question
**Created:** [July 6, 2026, 7:24am UTC](https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968 "2026-07-06T07:24:49Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Maucejo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maucejo/32/39090_2.png) [@Maucejo](https://discourse.julialang.org/u/Maucejo)
#### Post date: [July 6, 2026, 7:24am UTC](https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968/1 "2026-07-06T07:24:49Z")

</div>

Hi all, I am working on an optimization problem involving Complex Gaussian Processes and Kalman Filter. To optimize the hyperparameters of the kernels, I use Optimization.jl. Because I have calculated the analytical gradients, I can use gradient-based methods.

I define the `OptimizationFunction` as:

```julia
OptimizationFunction(objfun!, grad = objfun_gradient!)

```

It works, but `objfun!` and `objfun_gradient!` share a lot of computations. So, it would be ideal if I can define the objective function and its gradient in the same function in order to save computation time and resources.

My question is: Is it possible to do this with Optimization.jl? My understanding of the documentation is that it is not possible, but a clever solution may exist.

Thanks!

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [July 6, 2026, 7:57am UTC](https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968/2 "2026-07-06T07:57:47Z")

</div>

I think individual solvers like Optim.jl may support it, but it doesn’t seem to be planned for the interface library: see [Is there an equivalent to Optim.jl's only\_fg! ? · Issue #1101 · SciML/Optimization.jl · GitHub](http://github.com/SciML/Optimization.jl/issues/1101)

---

<div class="post-metadata">

### Author: ![Maucejo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maucejo/32/39090_2.png) [@Maucejo](https://discourse.julialang.org/u/Maucejo)
#### Post date: [July 6, 2026, 10:23am UTC](https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968/3 "2026-07-06T10:23:51Z")

</div>

@gdalle Thank you for your accurate answer (as usual).

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [July 7, 2026, 6:30am UTC](https://discourse.julialang.org/t/optimization-jl-define-the-objective-function-and-its-gradient-in-the-same-function/137968/4 "2026-07-07T06:30:44Z")

</div>

I think you can hack it together using a closure or a functor:

```julia-auto
mutable struct ComputeCache
    arg::Vector{Float64}
    func::Float64
    grad::Vector{Float64}
end

struct ObjFunc{F}<:Function
    cache::ComputeCache
    gf::F
end

struct GradObjFunc{F}<:Function
    cache::ComputeCache
    gf::F
end

function (fn::ObjFunc)(x)
    if x == fn.cache.arg
        return fn.cache.func
    else
        g, f = fn.gf(fn.cache.grad, x)
        fn.cache.arg .= x
        fn.cache.func = f
        return f
    end
end

function (fn::GradObjFunc)(grad, x)
    if x != fn.cache.arg
        g, f = fn.gf(fn.cache.grad, x)
        fn.cache.arg .= x
        fn.cache.func = f
    end
    grad .= fn.cache.grad
    return grad
end

cache = ComputeCache(...)

OptimizationFunction(ObjFunc(cache, gf!); grad=GradObjFunc(cache, gf!))

```
