# Adding nonlinear constraints in JuMP without hard-coding

**URL:** <https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626>\
**Category:** Optimization (Mathematical)\
**Created:** [January 14, 2022, 2:49pm UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626 "2022-01-14T14:49:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ReinhardMu](https://avatars.discourse-cdn.com/v4/letter/r/e79b87/32.png) [@ReinhardMu](https://discourse.julialang.org/u/ReinhardMu)\
**Post date:** [January 14, 2022, 2:49pm UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626/1 "2022-01-14T14:49:59Z")

</div>

Hi,

I am trying to do some kind of cutting-plan algorithm in JuMP.

I currently have the following example:

```julia
function generate_model(ydisc :: Vector{Vector{Float64}})
    model = Model(SCIP.Optimizer)

    @variable(model, 0 <= x[1:2] <= 6)
    @variable(model,0 <=z<=1)

     @objective(model, Min, 10-x[1])
     for (i,ydisc_i) in enumerate(ydisc)
         @NLconstraint(model, ((ydisc_i[1]^2/(1+exp(-40*(x[1]-ydisc_i[1])))+x[1]-ydisc_i[1]-2))<=0)
     end

    return model
end

```

As you can see, the expression for the constraint is hard-coded into the model.  
Is there a way that I can define this model for a general user defined function?

```julia
#define g outside, perhaps even as a lambda generated by another function
@NLconstraint(model, g(x,y_disc_i)<=0)

```

[Here](https://jump.dev/JuMP.jl/stable/manual/nlp/#No-operator-overloading) it says that “All nonlinear expressions must be inside of macros.” Does that mean, that I have to hard-code the functions. (I am new to Julia, usually use more Python or C++). Surprisingly, the EAGO.jl solver seems to have some operatoroverloading, so some experiments I tried only worked with that solver.

Regards

---

<div class="post-metadata">

**Author:** ![blob](https://avatars.discourse-cdn.com/v4/letter/b/ebca7d/32.png) [@blob](https://discourse.julialang.org/u/blob)\
**Post date:** [January 14, 2022, 3:17pm UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626/2 "2022-01-14T15:17:19Z")

</div>

You can use user-defined functions in JuMP, but you have to register them first: [Nonlinear Modeling · JuMP](https://jump.dev/JuMP.jl/stable/manual/nlp/#Register-a-function). You may want to look at the warnings about raw expressions in the link, if you need more flexibility.

---

<div class="post-metadata">

**Author:** ![ReinhardMu](https://avatars.discourse-cdn.com/v4/letter/r/e79b87/32.png) [@ReinhardMu](https://discourse.julialang.org/u/ReinhardMu)\
**Post date:** [January 14, 2022, 5:42pm UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626/3 "2022-01-14T17:42:39Z")

</div>

Thanks blob,

thanks for your help.  
I already saw that part of the documentation, but there are two problems for me

1. I want to use global solvers, but e.g.

```julia
using JuMP;
using Ipopt;
using AmplNLWriter
using Couenne_jll;

square(x) = x^2
f(x, y) = (x - 1)^2 + (y - 2)^2

function run()
#model = Model(Ipopt.Optimizer)
model = Model(() -> AmplNLWriter.Optimizer(Couenne_jll.amplexe))
register(model, :square, 1, square; autodiff = true)
register(model, :my_f, 2, f; autodiff = true)

@variable(model, 0.5<=x[1:2]<=2)
@NLobjective(model, Min, my_f(x[1], square(x[2])))
optimize!(model);
@show value.(model[:x])
end

run()

```

Does not work. Register only seems to work for methods that only require access to function evaluations and gradients.

1. In my use case, I would need something akin to anonymous registered functions. Giving the functions a predefined unique name (like my\_f) is not possible. I tried generating a unique name (like my\_f\_1 in the first iteration and my\_f\_2 in the second), but my knowledge about Julia Macros is far too shallow to succeed.

---

<div class="post-metadata">

**Author:** ![blob](https://avatars.discourse-cdn.com/v4/letter/b/ebca7d/32.png) [@blob](https://discourse.julialang.org/u/blob)\
**Post date:** [January 17, 2022, 8:44am UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626/4 "2022-01-17T08:44:38Z")

</div>

How about this example: [Nonlinear Modeling · JuMP](https://jump.dev/JuMP.jl/stable/manual/nlp/#More-complicated-examples) ? It creates names f\_1, f\_2.,… for functions that come from a vector of functions.

And what is the error you are getting with Couenne?

---

<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 18, 2022, 1:38am UTC](https://discourse.julialang.org/t/adding-nonlinear-constraints-in-jump-without-hard-coding/74626/5 "2022-01-18T01:38:28Z")

</div>

> [@ReinhardMu](#):
>
> Register only seems to work for methods that only require access to function evaluations and gradients

That’s correct.

If you’re using a solver that requires expression graphs as part of the specification of the input problem (most global solvers do, including SCIP and Couenne), then JuMP needs to see the expressions. This is not possible with `JuMP.register`. You may specify the constraints using macros or [raw expression input](https://jump.dev/JuMP.jl/stable/manual/nlp/#Raw-expression-input).
