# Computing common components in KNITRO callbacks

**URL:** https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014
**Category:** Optimization (Mathematical)
**Tags:** package
**Created:** [December 1, 2023, 7:25pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014 "2023-12-01T19:25:13Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![fimiller](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fimiller/32/51226_2.png) [@fimiller](https://discourse.julialang.org/u/fimiller)
#### Post date: [December 1, 2023, 7:25pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/1 "2023-12-01T19:25:13Z")

</div>

I am using KNITRO.jl to solve a particular optimization problem. In my optimization problem, there is a common calculation done across the constraint, jacobian for the constraint, and the hessian for the constraint.

Currently, I have this calculation done multiple times across each individual callback function. I wish to my code more efficient, and move the common calculation to its own function (or something similar), so that it is only being done for each updated x iterate. Does anyone have any tips for how to do this? Some example code is below:  
Essentially, I wish to have `f(x)` be precomputed to avoid this line, since in my case, `f` is quite slow. One issue I have been running into is that I am not able to mutate `userParams` after it is created, so I do not think I will be able to pass it there.

```julia
function callbackEvalC(kc, cb, evalRequest, evalResult, userParams)
   

    x = evalRequest.x 
    y = f(x)
    
    evalResult.c[1] = y
end 

function callbackEvalCGrad(kc, cb, evalRequest, evalResult, userParams)
   

    x = evalRequest.x 
    y = f(x)
    
    evalResult.jac[1] = 2 * y
end 

```

Thanks!

---

<div class="post-metadata">

### Author: ![cgeoga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cgeoga/32/216186_2.png) [@cgeoga](https://discourse.julialang.org/u/cgeoga)
#### Post date: [December 1, 2023, 10:20pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/2 "2023-12-01T22:20:07Z")

</div>

What I do for things like this is create a struct that carries around the extra things I want to store, and then give that structs the necessary methods so that I can pass it in in place of the straight callback functions as you write them here.

[Here](https://git.sr.ht/~cgeoga/StandaloneKNITRO.jl/tree/master/item/src/callbacks.jl) is my own KNITRO interface. I don’t cache things like function evaluations, although I’m sure it wouldn’t hurt to do. This code probably isn’t worth copying, but the point is that you could probably make an object like a

```julia
mutable struct MyModel
  xeval::Vector{Float64}
  feval::Float64
  [...]
end

```

and give it methods (for extra wrapper structs) like

```julia
struct Objective{M}
  m::M
end

function (obj::Objective{M})(kc, cb, evalRequest, evalResult, userParams) where{M<:MyModel}
  # now check if you already computed f(x) for evalRequest.x by doing something like this:
  if isapprox(evalRequest.x, obj.m.x)
    # skip the computation and use your stored result
  else
    # compute the new thing (and update the values in your obj.m!)
  end
end

```

This is probably just a clunkier version of what JuMP already does, so maybe @odow will chime in and say “don’t do that” and offer a better solution. But creating structs and giving them the necessary method is a general concept that will probably be useful for solving problems like these.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [December 1, 2023, 10:21pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/3 "2023-12-01T22:21:21Z")

</div>

You could use the caching trick that is shown here: [Nested optimization problems · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/nested_problems/#Improving-performance)

(Note also that i just released KNITRO.jl v0.14, which brings a number of breaking changes to the C API. The new API now much more closely matches the official KNITRO API.)

Is there any reason to use the low-level API instead of JuMP? Manually computing derivatives is a pretty common source of hard to diagnose bugs.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [December 1, 2023, 10:22pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/4 "2023-12-01T22:22:26Z")

</div>

Ha, we replied at the same time. Its the same caching trick so I approve.

---

<div class="post-metadata">

### Author: ![cgeoga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cgeoga/32/216186_2.png) [@cgeoga](https://discourse.julialang.org/u/cgeoga)
#### Post date: [December 1, 2023, 10:23pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/5 "2023-12-01T22:23:42Z")

</div>

Hey, alright! Best part of my day. Thanks for the note on the new release, also—I’ll have to go un-break my little wrapper.

---

<div class="post-metadata">

### Author: ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)
#### Post date: [December 1, 2023, 10:26pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/6 "2023-12-01T22:26:53Z")

</div>

The KNITRO low level API is now a lot simpler, in the sense that there is fewer bits of Julia-specific magic and helper methods. The downside is that some calls are more verbose.

The changes to the examples in [Rewrite the C wrapper by odow · Pull Request #268 · jump-dev/KNITRO.jl · GitHub](https://github.com/jump-dev/KNITRO.jl/pull/268/files) give a good sense of what to update.

(I also didnt notice your wrapper because it is not registered, sorry for the churn.)

---

<div class="post-metadata">

### Author: ![cgeoga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cgeoga/32/216186_2.png) [@cgeoga](https://discourse.julialang.org/u/cgeoga)
#### Post date: [December 1, 2023, 10:34pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/7 "2023-12-01T22:34:56Z")

</div>

No apologies necessary! This looks like a great set of improvements, and it is definitely only my responsibility to keep up with the low level API stuff that serious users like you are developing.

---

<div class="post-metadata">

### Author: ![fimiller](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fimiller/32/51226_2.png) [@fimiller](https://discourse.julialang.org/u/fimiller)
#### Post date: [December 5, 2023, 1:35pm UTC](https://discourse.julialang.org/t/computing-common-components-in-knitro-callbacks/107014/8 "2023-12-05T13:35:31Z")

</div>

Thanks for all the help! I think creating the mutable struct will work for my project.
