# Is there a Symbolics.jl interface to Ipopt (or similar)?

**URL:** https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149
**Category:** Modelling & Simulations
**Tags:** nlp, ipopt, modelling
**Created:** [June 10, 2023, 8:22pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149 "2023-06-10T20:22:51Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 10, 2023, 8:22pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/1 "2023-06-10T20:22:51Z")

</div>

Hello, is there an interface to Ipopt which can accept Symbolics functions?

There is NLPModelsIpopt, which accepts NLPModels. Going via ADNLPModels seems unnecessary as Symbolics can already provide all the hessians, jacobians etc…

I tried to implement a (VERY) quick proof of concept [SymNLPModels.jl](https://github.com/votroto/SymNLPModels.jl) package and it seems reasonably straightforward. Should I continue with it, or am reinventing the wheel?

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [June 10, 2023, 8:55pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/2 "2023-06-10T20:55:49Z")

</div>

Try [ADNLPModels](https://github.com/JuliaSmoothOptimizers/ADNLPModels.jl).

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 10, 2023, 9:02pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/3 "2023-06-10T21:02:42Z")

</div>

ADNLPModels seem to accept callable function only, not Symbolics.jl functions.

---

<div class="post-metadata">

### Author: ![Vaibhavdixit02](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vaibhavdixit02/32/2916_2.png) [@Vaibhavdixit02](https://discourse.julialang.org/u/Vaibhavdixit02)
#### Post date: [June 10, 2023, 9:03pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/4 "2023-06-10T21:03:00Z")

</div>

You can create an optimization problem with ModelingToolkit ([Modeling Optimization Problems · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/optimization/)) which uses Symbolics under the hood and instead using Optim wrapper as shown there use the OptimizationMOI sub-package from Optimization.jl [Modeling Optimization Problems · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/optimization/) to use Ipopt (shown in examples there)

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 10, 2023, 9:10pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/5 "2023-06-10T21:10:51Z")

</div>

Interesting! Two questions:

1. If the Symbolics expressions already exist – e.g. being changed throughout the course of an iterative algorithm – can ModelingToolkit accept them?
2. Can MOI really handle arbitrary Symbolics expressions, or will I have to fight it?

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [June 10, 2023, 11:13pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/6 "2023-06-10T23:13:59Z")

</div>

> [@votroto](#):
>
> If the Symbolics expressions already exist – e.g. being changed throughout the course of an iterative algorithm – can ModelingToolkit

Yes

> [@votroto](#):
>
> Can MOI really handle arbitrary Symbolics expressions, or will I have to fight it?

Yes we give MOI functions.

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 11, 2023, 2:14am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/7 "2023-06-11T02:14:19Z")

</div>

That is a rather overwhelming collection of packages. Could I get a little hint, please? It seems I am missing a level of indirection.

```julia
using ModelingToolkit
using OptimizationMOI
using Ipopt

vars = @variables x y

objective = 5*x*y^2 - 2*x^2 + y^3 - 1
constraints = [x^2 ≲ 1, y^2 ≲ 1]

@named os = OptimizationSystem(objective, vars, []; constraints)

u0 = vars .=> 0.
prob = OptimizationProblem(os, u0; grad = true, hess = true)

sol = solve(prob, Ipopt.Optimizer())

```

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [June 11, 2023, 3:49am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/8 "2023-06-11T03:49:11Z")

</div>

@Vaibhavdixit02 is going to write a tutorial on this. That’s probably the most productive way to share this information given that indeed the documentation on this is currently too sparse.

---

<div class="post-metadata">

### Author: ![Vaibhavdixit02](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vaibhavdixit02/32/2916_2.png) [@Vaibhavdixit02](https://discourse.julialang.org/u/Vaibhavdixit02)
#### Post date: [June 11, 2023, 7:51am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/9 "2023-06-11T07:51:32Z")

</div>

> [@votroto](#):
>
> ```julia
> using ModelingToolkit
> using OptimizationMOI
> using Ipopt
> 
> vars = @variables x y
> 
> objective = 5*x*y^2 - 2*x^2 + y^3 - 1
> constraints = [x^2 ≲ 1, y^2 ≲ 1]
> 
> @named os = OptimizationSystem(objective, vars, []; constraints)
> 
> u0 = vars .=> 0.
> prob = OptimizationProblem(os, u0; grad = true, hess = true)
> 
> sol = solve(prob, Ipopt.Optimizer())
> 
> ```

Since Ipopt needs the contraints’ jacobian and hessians hence you’d need to switch them on in the `OptimizationProblem`

`prob = OptimizationProblem(os, u0; grad = true, hess = true, cons_j = true, cons_h = true)`

---

<div class="post-metadata">

### Author: ![Vaibhavdixit02](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vaibhavdixit02/32/2916_2.png) [@Vaibhavdixit02](https://discourse.julialang.org/u/Vaibhavdixit02)
#### Post date: [June 11, 2023, 7:53am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/10 "2023-06-11T07:53:20Z")

</div>

The tutorial for this case already exists [Modeling Optimization Problems · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/optimization/#Rosenbrock-Function-with-Constraints)

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 11, 2023, 2:57pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/11 "2023-06-11T14:57:37Z")

</div>

> [@Vaibhavdixit02](#):
>
> prob = OptimizationProblem(os, u0; grad = true, hess = true, cons\_j = true, cons\_h = true)

That works great, thank you! 🙂

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [June 11, 2023, 3:12pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/12 "2023-06-11T15:12:44Z")

</div>

> [@Vaibhavdixit02](#):
>
> Since Ipopt needs the contraints’ jacobian and hessians hence you’d need to switch them on in the `OptimizationProblem`

What does the current error message say? It might need to be more explicit if the user didn’t figure this one out.

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 11, 2023, 5:40pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/13 "2023-06-11T17:40:48Z")

</div>

> [@ChrisRackauckas](#):
>
> What does the current error message say? It might need to be more explicit if the user didn’t figure this one out.

Oh, it’s probably down to my inexperience with the project, so I did not want to bother you with it.

It says `Use OptimizationFunction to pass the derivatives or automatically generate them with one of the autodiff backends`, which I interpreted to mean that the OptimizationMOI package implements a “OptimizationFunction” as some kind of an adapter class to MOI, and wants me to use it instead of OptimizationProblem.

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 11, 2023, 5:52pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/14 "2023-06-11T17:52:01Z")

</div>

I would say a clearer message would be

```julia
Enable automatic generation of derivatives in $(TypeName), or pass them directly.

```

Where TypeName would be the type-name of whatever was passed in (OptimizationProblem), if it supports it (or list of the ones that do).

---

<div class="post-metadata">

### Author: ![tmigot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tmigot/32/23914_2.png) [@tmigot](https://discourse.julialang.org/u/tmigot)
#### Post date: [June 13, 2023, 7:14am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/15 "2023-06-13T07:14:31Z")

</div>

Hey @votroto!

Note that we are adding several backends to compute derivatives in ADNLPModels and in particular it is possible to compute the Jacobian and Hessian with Symbolics (so adding the gradient wouldn’t be difficult - if you are interested in contributing).

The following works:

```julia
using ADNLPModels, Symbolics, NLPModels

@variables x
objective = (x - 3)^2

variables = Symbolics.get_variables(objective)
build(f) = Symbolics.build_function(f, variables; expression=false)
f = build(objective)

T = Float64
nlp = ADNLPModel(f, zeros(T, 2), hessian_backend = ADNLPModels.SparseSymbolicsADHessian)
hess(nlp, nlp.meta.x0)

```

I hope you understand that even though the model is handled with Symbolics expression, Ipopt does not perform symbolic computations internally.

---

<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: [June 13, 2023, 8:19am UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/16 "2023-06-13T08:19:34Z")

</div>

I’ll also leave the JuMP example here for completeness:

```julia
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, x, start = 0)
@variable(model, y, start = 0)
@NLobjective(model, Min, 5*x*y^2 - 2*x^2 + y^3 - 1)
@constraint(model, x^2 <= 1)
@constraint(model, y^2 <= 1)
optimize!(model)
value(x), value(y)

```

---

<div class="post-metadata">

### Author: ![votroto](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/votroto/32/16416_2.png) [@votroto](https://discourse.julialang.org/u/votroto)
#### Post date: [June 14, 2023, 10:04pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/17 "2023-06-14T22:04:23Z")

</div>

Odow, JuMP cannot directly send DynamicPolynomials or Symbolics to Ipopt, can it?

But even in static cases, let’s say your example is closer to (This example is made up and has no meaning):

```julia
using ModelingToolkit, OptimizationMOI, Ipopt
ADPARAMS = (;grad = true, hess = true, cons_j = true, cons_h = true)

f(p, q) = (1 / sqrt(2π)) * exp(-((p - q)^2) / 2)
total(p, q) = sum(_p * f(i, q) for (i, _p) in enumerate(p))
l1(p, q) = 1 - total(p, q) + 0.5 * total(p, 0.5)
l2(p, q) = total(p, q) - 1
lhs(p, q, _q) = l1(p, q) - l1(p, _q)

function approximate(Q)
    @variables p[1:5] [bounds = (-2.0, 2.0)]
    @variables w [bounds = (-1.0, 3.0)] 
    @variables q [bounds = (-1.0, 3.0)]
    variables = [p; w; q]

    constraints = [w*lhs(p, q, _q) + (1-w)*l2(p, q) ≲ 0 for _q in Q]
    @named os = OptimizationSystem(w, variables, []; constraints)
    prob = OptimizationProblem(os, randn(length(variables)); ADPARAMS...)
    return solve(prob, Ipopt.Optimizer())
end

approximate(-0.8:0.4:0.8)

```

I always struggle in JuMP to model NLPs involving arrays, summations, polynomials, custom multi-argument functions etc. Maybe I’m doing it wrong, idk…

---

<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: [June 14, 2023, 10:49pm UTC](https://discourse.julialang.org/t/is-there-a-symbolics-jl-interface-to-ipopt-or-similar/100149/18 "2023-06-14T22:49:05Z")

</div>

> I always struggle in JuMP to model NLPs involving arrays, summations, polynomials, custom multi-argument functions etc

Yeah this is a known problem. For now you’d need to do some ugly hack like:

```Julia
using JuMP, Ipopt
begin
    Q = -0.8:0.4:0.8
    model = Model(Ipopt.Optimizer)
    @variable(model, -2 <= p[1:5] <= 2)
    @variable(model, -1 <= w <= 3)
    @variable(model, -1 <= q <= 3)
    @objective(model, Min, w)
    total = Dict(
        _q => @NLexpression(
            model, 
            sum(_p / sqrt(2π) * exp(-(i - _q)^2 / 2) for (i, _p) in enumerate(p))
        )
        for _q in Any[Q; q; 0.5]
    )
    l1 = Dict(
        _q => @NLexpression(model, 1 - total[_q] + 0.5 * total[0.5])
        for _q in Any[Q; q]
    )
    @NLconstraint(
        model, 
        [_q in Q], 
        w * (l1[q] - l1[_q]) + (1 - w) * (total[q] - 1) <= 0
    )
    optimize!(model)
end

```

We’re working on fixing this, but it’s not ready yet: [https://github.com/jump-dev/JuMP.jl/pull/3106#issuecomment-1592091623](https://github.com/jump-dev/JuMP.jl/pull/3106#issuecomment-1592091623)
