# JuMP interface access to automatic differentiation (ReverseDiffSparse)

**URL:** <https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354>\
**Category:** Optimization (Mathematical)\
**Tags:** jump, differentiation\
**Created:** [January 13, 2018, 10:28pm UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354 "2018-01-13T22:28:37Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacob-roth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacob-roth/32/1862_2.png) [@jacob-roth](https://discourse.julialang.org/u/jacob-roth)\
**Post date:** [January 13, 2018, 10:28pm UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/1 "2018-01-13T22:28:37Z")

</div>

I’m trying to use `ReverseDiffSparse` to return the gradient and Hessian of a scalar valued function `f`. I only need to evaluate the gradient and Hessian (i.e., I don’t need to set up a whole model). I saw from the JuMP Documentation that I can access automatic differentiation through JuMP using `MathProgBase` per the following example.

```julia
m = Model()
@variable(m, x)
@variable(m, y)

@NLobjective(m, Min, sin(x) + sin(y))
values = zeros(2)
values[linearindex(x)] = 2.0
values[linearindex(y)] = 3.0

d = JuMP.NLPEvaluator(m)
MathProgBase.initialize(d, [:Grad])
objval = MathProgBase.eval_f(d, values) # == sin(2.0) + sin(3.0)

∇f = zeros(2)
MathProgBase.eval_grad_f(d, ∇f, values)
# ∇f[linearindex(x)] == cos(2.0)
# ∇f[linearindex(y)] == cos(3.0)

```

Three questions:

1. Is this using `ReverseDiffSparse`?

2. Is there a better way of returning the gradient and Hessian than setting up a model and using `MathProgBase.eval_grad_f`?

3. (not necessary if (2) is solved) If I define my function `f(x,y)` as returning `sin(x) + cos(y)` how can I insert this into `@NLobjective(m, Min, sin(x) + sin(y))`? I tried `@NLobjective(m, Min, f(x,y))`, but I get the following error:

```julia
Unrecognized function "f" used in nonlinear expression.

Stacktrace:
 [1] error(::String) at ./error.jl:21
 [2] include_string(::String, ::String) at ./loading.jl:515

```

Thanks!

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [January 13, 2018, 11:35pm UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/2 "2018-01-13T23:35:41Z")

</div>

> [@jacob-roth](#):
>
> Is this using ReverseDiffSparse?

Yes, JuMP always uses ReverseDiffSparse.

> [@jacob-roth](#):
>
> Is there a better way of returning the gradient and Hessian than setting up a model and using MathProgBase.eval\_grad\_f?

No, this is the best and only documented way to do so.

> [@jacob-roth](#):
>
> (not necessary if (2) is solved) If I define my function f(x,y) as returning sin(x) + cos(y) how can I insert this into @NLobjective(m, Min, sin(x) + sin(y))? I tried @NLobjective(m, Min, f(x,y)), but I get the following error:

We call this a [user-defined function](http://www.juliaopt.org/JuMP.jl/0.18/nlp.html#user-defined-functions). It needs to be registered first. However, Hessians are not available if there are non-univariate user-defined functions present.

---

<div class="post-metadata">

**Author:** ![jacob-roth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacob-roth/32/1862_2.png) [@jacob-roth](https://discourse.julialang.org/u/jacob-roth)\
**Post date:** [January 14, 2018, 8:01pm UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/3 "2018-01-14T20:01:02Z")

</div>

Thanks! As a follow up, I’ve tried to evaluate the Hessian in the original example but am unsuccessful. My additional code is:

```julia
MathProgBase.initialize(d, [:Grad,:Hess])
H = zeros(2); # based on MathProgBase.hesslag_structure(d) = ([1,2],[1,2])
MathProgBase.eval_hesslag(d, H, values, 0, [0])

```

but I get the following error (for various attempts at matching the types of `H, x, σ, μ` to those specified in the candidate methods):

```julia
MethodError: no method matching eval_hesslag(::JuMP.NLPEvaluator, ::Array{Float64,1}, ::Array{Float64,1}, ::Int64, ::Int64)
Closest candidates are:
  eval_hesslag(::MathProgBase.SolverInterface.LPQPEvaluator, ::Any, ::Any, ::Any, ::Any) at /Users/MYUSER/.julia/v0.6/MathProgBase/src/SolverInterface/nonlinear_to_lpqp.jl:272
  eval_hesslag(::JuMP.NLPEvaluator, ::Array{Float64,1}, ::Array{Float64,1}, ::Float64, ::Array{Float64,1}) at /Users/MYUSER/.julia/v0.6/JuMP/src/nlp.jl:748

Stacktrace:
 [1] include_string(::String, ::String) at ./loading.jl:515

```

Is there a simple fix? Finally, If I’m able to evaluate the Hessian, is there a way of extracting the intermediary gradient too?

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [January 15, 2018, 4:47am UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/4 "2018-01-15T04:47:46Z")

</div>

> [@jacob-roth](#):
>
> Is there a simple fix?

Yes, call the method with arguments that match its (strict) type signature:

```julia
MathProgBase.eval_hesslag(d, H, values, 0.0, Float64[])

```

> [@jacob-roth](#):
>
> Finally, If I’m able to evaluate the Hessian, is there a way of extracting the intermediary gradient too?

Use `eval_grad_f`. If you take a peek at the implementation you see that some computation is avoided if you’ve already evaluated the Hessian at the same point.

> <https://github.com/jump-dev/JuMP.jl/blob/b0fb982db51f481df4cf332275b8a5ef8e6e3101/src/nlp.jl#L535>

---

<div class="post-metadata">

**Author:** ![jacob-roth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacob-roth/32/1862_2.png) [@jacob-roth](https://discourse.julialang.org/u/jacob-roth)\
**Post date:** [February 14, 2018, 4:44pm UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/5 "2018-02-14T16:44:03Z")

</div>

Quick follow-up: I’ve been able to query JuMP for gradients / Hessians in unconstrained problems, but is there a standard way of doing this for constrained problems?

I tried the naive approach of adding a constraint to a NL model (for example: adding `@constraint(m, x1 + x2 == 10.0)` after my objective `@NLobjective(m, Min, x1^2 + x2^2 + x1*x2^2)`), but querying for the Hessian with ` MathProgBase.eval_hesslag(d, v, values, 1., Float64[1., 1.])` still gave me the Hessian of the objective (and I’d prefer not to augment the objective with a penalty).

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [February 15, 2018, 2:18am UTC](https://discourse.julialang.org/t/jump-interface-access-to-automatic-differentiation-reversediffsparse/8354/6 "2018-02-15T02:18:53Z")

</div>

[`eval_hesslag`](http://mathprogbasejl.readthedocs.io/en/latest/nlp.html#eval_hesslag) is the standard way to do this. You can drop the contribution from the objective by setting the `σ` argument to zero. You won’t see much going on if you only have linear constraints, however, because they never appear in the Hessian.
