# User defined objective function to run MICP

**URL:** <https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [October 31, 2018, 3:19am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992 "2018-10-31T03:19:00Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [October 31, 2018, 3:19am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/1 "2018-10-31T03:19:00Z")

</div>

I have the following objective function (w is the variable vector of size nx):

```julia
function obj_trace(w::Array{Float64,1})
    dg = Diagonal(w)
    M = F' * (gamma \ dg) * F + eye(nx)
    obj = trace(inv(M))
    return obj
end 

```

where gamma is diagonal (F, nx, gamma are given), and the following constraints:  
(1) sum(w) \<= c (a known integer);  
(2) each element in w is binary (either 0 or 1).

I have tried Pajarito package in Julia using a different formulation: add SDP constraints and no user-defined function. The algorithm (Mosek + CPLEX) does not seem to stop even for small n. Is there a better (faster) way to solve this MICP with user-defined function (ideally i would like to use Ipopt as cont-solver, and provide user-defined gradient and hessian as well)?

Any suggestion is appreciated!

---

<div class="post-metadata">

**Author:** ![chriscoey](https://avatars.discourse-cdn.com/v4/letter/c/3ab097/32.png) [@chriscoey](https://discourse.julialang.org/u/chriscoey)\
**Post date:** [October 31, 2018, 3:39am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/2 "2018-10-31T03:39:16Z")

</div>

Hi! Pajarito only accepts conic models - see the conic section of the mathprogbase documentation. Pavito is another MICP solver that only accepts NLP models - see the nonlinear programming section of mathprogbase docs. If you need to have SDP constraints, then you should use Pajarito, which will require that you rewrite any NLP constraints in conic form. Convex.jl is a package that does this automatically, though it currently may emit many deprecation warnings and you may need to use the branch in the open PR for the 0.7 update (if you use Julia 0.7+).

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [October 31, 2018, 5:07pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/3 "2018-10-31T17:07:19Z")

</div>

Thank you for the suggestion and information about Pavito! I do not have to use SDP constraints, and initially my objective is defined as a function and I have also computed its gradient and hessian, so i would like to use Ipopt to solve the relaxed continuous problem with user-defined (func, grad, hess). However, I am not sure how to write it in Julia with a MICP solver.

---

<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:** [October 31, 2018, 5:54pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/4 "2018-10-31T17:54:04Z")

</div>

Pavito is able to use Ipopt for continuous relaxations and take user-defined functions through JuMP. However, JuMP does not support providing hessians for user-defined functions ([Feature Request: Second Derivatives for User Defined Functions · Issue #1198 · jump-dev/JuMP.jl · GitHub](https://github.com/JuliaOpt/JuMP.jl/issues/1198)). You could also call Bonmin through its C++ API.

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [October 31, 2018, 6:27pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/5 "2018-10-31T18:27:56Z")

</div>

Thank you for suggesting Bonmin in C++, but I would like to try that later if this does not work in Julia. Indeed Pavito can use IpoptSolver as cont-solver and I have tried it as follows, but Julia returned an error.

```julia
using JuMP, Pavito
nx = 100
c = 10
F = rand(nx, nx)

function my_obj(w...)
    M = eye(nx)
    for i = 1 : nx
        M += w[i] * F[:, i]' * F[:, i]
    end
    return trace(inv(M))
end

mip_solver_drives = true
rel_gap = 1e-5

using CPLEX
mip_solver = CplexSolver(
    CPX_PARAM_SCRIND = (mip_solver_drives ? 1 : 0),
    CPX_PARAM_EPINT = 1e-8,
    CPX_PARAM_EPRHS = 1e-7,
    CPX_PARAM_EPGAP=(mip_solver_drives ? 1e-5 : 1e-9)
)

using Ipopt
cont_solver = IpoptSolver(print_level = 0)

solver = PavitoSolver(
    mip_solver_drives = mip_solver_drives,
    log_level = 1,
    rel_gap = rel_gap,
    mip_solver = mip_solver,
    cont_solver = cont_solver,
)

model = Model(solver = solver)
JuMP.register(model, :my_obj, nx, my_obj, autodiff = true)
w = @variable(model, [j = 1 : nx], Bin, lowerbound = 0, upperbound = 1)
@constraint(model, sum(w) <= c)
@NLobjective(model, Min, my_obj(w))

```

Error message: LoadError: Incorrect number of arguments for “my\_obj” in nonlinear expression. This is also related to a previous question: [https://discourse.julialang.org/t/passing-an-array-of-variables-to-a-user-defined-non-linear-function/4132](https://discourse.julialang.org/t/passing-an-array-of-variables-to-a-user-defined-non-linear-function/4132).

Currently I use auto-diff in the code, but I will provide gradient after the code can run for the simpler case. Could you give some advice on how I should define the function ?

---

<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:** [October 31, 2018, 8:58pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/6 "2018-10-31T20:58:30Z")

</div>

> [@PSA: how to quote code with backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530):
>
> This is a short post on how to use backticks (` and ```) to quote code, so it is easy to read. This post can be linked to new users who are confused by this feature. Why By quoting your code, you get a monospaced font (which preserves indentation) and syntax highlighting. This makes it easier to read your code and help you. Displayed code looks like this: function displayed\_code(x::Int, y::Int) if x \< y println("x is smaller") else println("or not") end end Inline…

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [October 31, 2018, 9:35pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/7 "2018-10-31T21:35:38Z")

</div>

Thank you very much for the comment, and I have edited my code.

---

<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:** [November 2, 2018, 1:48am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/8 "2018-11-02T01:48:23Z")

</div>

I can’t run your code because `F` and `nx` are not defined. When posting code, try to make it as small as possible and totally self-contained. Here is a minimal working example that demonstrates the same problem:

```julia
using JuMP
model = Model()
f(x, y) = x^y
JuMP.register(model, :f, 2, f, autodiff=true)
@variable(model, x[1:2] >= 0)
@NLobjective(model, Min, f(x...)) # Error: incorrect number of arguments

```

If you follow the advice at the end of the link you linked to, you can set the objective as:

```julia
JuMP.setNLobjective(model, :Min, Expr(:call, :f, x...))

```

Hope that helps!

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [November 2, 2018, 3:48pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/9 "2018-11-02T15:48:21Z")

</div>

That helps indeed! However, it was not solved properly:

```julia
using JuMP, Pavito
nx = 10
c = 2
F = rand(nx, nx)

function my_obj(w...)
    M = eye(nx)
    for i = 1 : nx
        M += w[i] * F[:, i]' * F[:, i]
    end
    return trace(inv(M))
end

mip_solver_drives = true
rel_gap = 1e-5

using CPLEX
mip_solver = CplexSolver(
    CPX_PARAM_SCRIND = (mip_solver_drives ? 1 : 0),
    CPX_PARAM_EPINT = 1e-8,
    CPX_PARAM_EPRHS = 1e-7,
    CPX_PARAM_EPGAP=(mip_solver_drives ? 1e-5 : 1e-9)
)

using Ipopt
cont_solver = IpoptSolver(print_level = 0)

solver = PavitoSolver(
    mip_solver_drives = mip_solver_drives,
    log_level = 1,
    rel_gap = rel_gap,
    mip_solver = mip_solver,
    cont_solver = cont_solver,
)

model = Model(solver = solver)
JuMP.register(model, :my_obj, nx, my_obj, autodiff = true)
w = @variable(model, [j = 1 : nx], Bin, lowerbound = 0, upperbound = 1)
@constraint(model, sum(w) <= c)
# @NLobjective(model, Min, my_obj(w))
@eval @JuMP.NLobjective(model, Min, $(Expr(:call, :my_obj, [Expr(:ref, :w, i) for i = 1 : nx]...)))
println("solution\n$(getvalue(w))\n")

```

It gave me the solution of all NaNs with a warning: “Variable value not defined for component of **anon**. Check that the model was properly solved.” The current Julia version is 0.6. Is there anything I am missing here?

---

<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:** [November 2, 2018, 3:56pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/10 "2018-11-02T15:56:46Z")

</div>

Did you try:

```julia
JuMP.setNLobjective(model, :Min, Expr(:call, :my_obj, w...))

```

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [November 2, 2018, 9:46pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/11 "2018-11-02T21:46:54Z")

</div>

yes i just tried, and this time it returned NaNs without warnings…

---

<div class="post-metadata">

**Author:** ![Olegg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olegg/32/51316_2.png) [@Olegg](https://discourse.julialang.org/u/Olegg)\
**Post date:** [November 23, 2018, 1:42am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/12 "2018-11-23T01:42:29Z")

</div>

I’m not an expert on julia, so it’s just a hypothesis. Did you set the start values for the variable vector? If not, since loweround = 0, the initial value may be a zero vector. So then the obj\_trace function may have division by 0, and hence produce NaNs.

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [November 23, 2018, 1:54am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/13 "2018-11-23T01:54:15Z")

</div>

Thank you for point it out. Right, i have not set the starting point. But even if the initial value is zero vector, the M matrix is identity plus a semidefinite matrix, so it’s always invertible, and would not return NaNs.

---

<div class="post-metadata">

**Author:** ![Olegg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olegg/32/51316_2.png) [@Olegg](https://discourse.julialang.org/u/Olegg)\
**Post date:** [November 23, 2018, 2:18am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/14 "2018-11-23T02:18:27Z")

</div>

Ah yes, sorry! Must be another reason.  
When you used Pavito, did you get the “Unsupported feature Hess” error? It’s just that JuMP doesn’t support Hessians for user-defined vector functions. That’s the error I was getting with Pavito and Ipopt + CbcSolver. Might be MILP solver-dependent though.

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [November 30, 2018, 5:34pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/15 "2018-11-30T17:34:52Z")

</div>

Yes, I got exactly the same error “Unsupported feature Hess”, but with Ipopt + CPLEX.

---

<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:** [November 30, 2018, 5:38pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/16 "2018-11-30T17:38:57Z")

</div>

See [Disable Hessians when not provided by JuMP by spockoyno · Pull Request #12 · jump-dev/Pavito.jl · GitHub](https://github.com/JuliaOpt/Pavito.jl/pull/12)

Pavito just needs a new release.

---

<div class="post-metadata">

**Author:** ![ccoffrin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccoffrin/32/400_2.png) [@ccoffrin](https://discourse.julialang.org/u/ccoffrin)\
**Post date:** [December 1, 2018, 9:46pm UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/17 "2018-12-01T21:46:11Z")

</div>

New version tagged. Please let us know if there are still any issues.

[https://github.com/JuliaLang/METADATA.jl/pull/19819](https://github.com/JuliaLang/METADATA.jl/pull/19819)

---

<div class="post-metadata">

**Author:** ![coiacy](https://avatars.discourse-cdn.com/v4/letter/c/7cd45c/32.png) [@coiacy](https://discourse.julialang.org/u/coiacy)\
**Post date:** [December 2, 2018, 12:55am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/18 "2018-12-02T00:55:47Z")

</div>

The code can run without error now. Nice! Hope the next step is to allow for user-defined hessian. Please let me know if there is a way to pass user defined (val, grad, hess) to Pavito.

---

<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:** [December 2, 2018, 11:01am UTC](https://discourse.julialang.org/t/user-defined-objective-function-to-run-micp/16992/19 "2018-12-02T11:01:21Z")

</div>

> [@coiacy](#):
>
> Please let me know if there is a way to pass user defined (val, grad, hess) to Pavito.

There is no way to do so through JuMP ([Feature Request: Second Derivatives for User Defined Functions · Issue #1198 · jump-dev/JuMP.jl · GitHub](https://github.com/JuliaOpt/JuMP.jl/issues/1198)). You could call Pavito through MathProgBase which would let you implement the derivative callbacks for the complete model.
