# JuMP register function

**URL:** https://discourse.julialang.org/t/jump-register-function/125099
**Category:** Optimization (Mathematical)
**Created:** [January 23, 2025, 5:34am UTC](https://discourse.julialang.org/t/jump-register-function/125099 "2025-01-23T05:34:14Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Sushrut\_Deshpande](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sushrut_deshpande/32/52754_2.png) [@Sushrut\_Deshpande](https://discourse.julialang.org/u/Sushrut_Deshpande)
#### Post date: [January 23, 2025, 5:34am UTC](https://discourse.julialang.org/t/jump-register-function/125099/1 "2025-01-23T05:34:14Z")

</div>

Hello,  
This is my first time using JuMP hence my question is basic.

The following fails

```julia
using JuMP, Ipopt

f(x) = x[1]^2 + x[2]^2
∇f(x) = [2*x[1], 2*x[2]]
∇²f(x) = [2 0; 0 2]
model = Model(Ipopt.Optimizer)
register(model, :my_fun, 1, f,∇f, ∇²f)
lb = [-1.0, -1.0]
ub = [1.0, 1.0]
@variable(model, lb[i] <= x[i=1:2] <= ub[i])
@NLobjective(model, Min, my_fun(x))
JuMP.optimize!(model)

```

with the error:

```julia
ERROR: LoadError: Unexpected array VariableRef[x[1], x[2]] in nonlinear expression. Nonlinear expressions may contain only scalar expressions.

```

The same occurs if I define the function as:

```julia
function my_function(x::T...) where {T<:Real}
    y = zeros(T, length(x))
    for i in eachindex(y)
        y[i] = x[i]^2
    end
    return sum(y)
end

```

I do not know why this occurs.  
Any help is appreciated.

---

<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: [January 23, 2025, 5:45am UTC](https://discourse.julialang.org/t/jump-register-function/125099/2 "2025-01-23T05:45:08Z")

</div>

Hi @Sushrut_Deshpande, welcome to JuMP!

See the documentation: [Nonlinear Modeling · JuMP](https://jump.dev/JuMP.jl/stable/manual/nonlinear/#jump_user_defined_operators)

The correct syntax is:

```Julia
julia> using JuMP, Ipopt

julia> f(x...) = x[1]^2 + x[2]^2
f (generic function with 1 method)

julia> function ∇f(g, x...)
           g[1] = 2*x[1]
           g[2] = 2*x[2]
       end
∇f (generic function with 1 method)

julia> function ∇²f(H, x...)
           H[1, 1] = 2.0
           H[2, 2] = 2.0
       end
∇²f (generic function with 1 method)

julia> model = Model(Ipopt.Optimizer)
A JuMP Model
├ solver: Ipopt
├ objective_sense: FEASIBILITY_SENSE
├ num_variables: 0
├ num_constraints: 0
└ Names registered in the model: none

julia> @operator(model, op_fun, 2, f, ∇f, ∇²f)
NonlinearOperator(f, :op_fun)

julia> lb = [-1.0, -1.0]
2-element Vector{Float64}:
 -1.0
 -1.0

julia> ub = [1.0, 1.0]
2-element Vector{Float64}:
 1.0
 1.0

julia> @variable(model, lb[i] <= x[i in 1:2] <= ub[i])
2-element Vector{VariableRef}:
 x[1]
 x[2]

julia> @objective(model, Min, op_fun(x...))
op_fun(x[1], x[2])

julia> optimize!(model)

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit https://github.com/coin-or/Ipopt
******************************************************************************

This is Ipopt version 3.14.17, running with linear solver MUMPS 5.7.3.

Number of nonzeros in equality constraint Jacobian...: 0
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 3

Total number of variables............................: 2
                     variables with only lower bounds: 0
                variables with lower and upper bounds: 2
                     variables with only upper bounds: 0
Total number of equality constraints.................: 0
Total number of inequality constraints...............: 0
        inequality constraints with only lower bounds: 0
   inequality constraints with lower and upper bounds: 0
        inequality constraints with only upper bounds: 0

iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls
   0 0.0000000e+00 0.00e+00 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0
   1 0.0000000e+00 0.00e+00 0.00e+00 -1.7 0.00e+00 - 1.00e+00 1.00e+00 0
   2 0.0000000e+00 0.00e+00 0.00e+00 -3.8 0.00e+00 - 1.00e+00 1.00e+00T 0
   3 0.0000000e+00 0.00e+00 0.00e+00 -5.7 0.00e+00 - 1.00e+00 1.00e+00T 0
   4 0.0000000e+00 0.00e+00 0.00e+00 -8.6 0.00e+00 - 1.00e+00 1.00e+00T 0

Number of Iterations....: 4

                                   (scaled) (unscaled)
Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00
Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00
Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00
Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00
Complementarity.........: 2.5059035596800808e-09 2.5059035596800808e-09
Overall NLP error.......: 2.5059035596800808e-09 2.5059035596800808e-09

Number of objective function evaluations = 5
Number of objective gradient evaluations = 5
Number of equality constraint evaluations = 0
Number of inequality constraint evaluations = 0
Number of equality constraint Jacobian evaluations = 0
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 4
Total seconds in IPOPT = 1.762

EXIT: Optimal Solution Found.

```

But if function tracing works, you can do:

```Julia
using JuMP, Ipopt
f(x...) = x[1]^2 + x[2]^2
model = Model(Ipopt.Optimizer)
lb = [-1.0, -1.0]
ub = [1.0, 1.0]
@variable(model, lb[i] <= x[i in 1:2] <= ub[i])
@objective(model, Min, my_fun(x...))
optimize!(model)

```

but even simpler, you can do:

```Julia
using JuMP, Ipopt
model = Model(Ipopt.Optimizer);
@variable(model, -1 <= x[i in 1:2] <= 1)
@objective(model, Min, x[1]^2 + x[2]^2)
optimize!(model)

```

---

<div class="post-metadata">

### Author: ![Sushrut\_Deshpande](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sushrut_deshpande/32/52754_2.png) [@Sushrut\_Deshpande](https://discourse.julialang.org/u/Sushrut_Deshpande)
#### Post date: [January 23, 2025, 5:50am UTC](https://discourse.julialang.org/t/jump-register-function/125099/3 "2025-01-23T05:50:24Z")

</div>

Hello,  
Thank you for the answer.  
I have just 1 small question now:  
What would be the difference between using `@operator` and `register`, the syntax seems to be same.

by intuition wouldn’t I `register` a custom 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: [January 23, 2025, 6:27am UTC](https://discourse.julialang.org/t/jump-register-function/125099/4 "2025-01-23T06:27:01Z")

</div>

See [ANN: JuMP v1.15 is released](https://discourse.julialang.org/t/ann-jump-v1-15-is-released/103875)

register is the old syntax.

---

<div class="post-metadata">

### Author: ![Sushrut\_Deshpande](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sushrut_deshpande/32/52754_2.png) [@Sushrut\_Deshpande](https://discourse.julialang.org/u/Sushrut_Deshpande)
#### Post date: [January 23, 2025, 6:33am UTC](https://discourse.julialang.org/t/jump-register-function/125099/5 "2025-01-23T06:33:44Z")

</div>

thank you
