# Nonlinear objective with both splatted variable and vector parameters

**URL:** <https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [April 22, 2023, 4:17pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791 "2023-04-22T16:17:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [April 22, 2023, 4:17pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/1 "2023-04-22T16:17:12Z")

</div>

Hi,

I’m currently writing a [model predictive control](https://github.com/franckgaga/ModelPredictiveControl.jl) package. The JuMP package is really helpful, thanks for everything.

For nonlinear programming, my decision variable is a vector so I need to rely on the splatting syntax. I also need vector nonlinear parameters with `@NLparameter(model, x[i=1:n] == x_val[i])`. Knowing that :

> The expression splatted can be _only_ a symbol. More complex expressions are not recognized.

is there a way to create an objective function both with nonscalar decision variable and nonscalar parameters as argument ?

For example, I can do:

```julia
using JuMP, Ipopt
function myfunc()
    model = Model(Ipopt.Optimizer)
    nvar = 3
    @variable(model, x[1:nvar])
    @NLparameter(model, a == 1)
    f(a, x...) = sum((x .- a).^2)
    register(model, :f, 1+nvar, f; autodiff = true)
    @NLobjective(model, Min, f(a, x...))
    optimize!(model)
    value.(x)
end
myfunc()

```

but this:

```julia
using JuMP, Ipopt
function myfunc()
    model = Model(Ipopt.Optimizer)
    nvar = 3
    @variable(model, x[1:nvar])
    @NLparameter(model, a[i=1:nvar] == 1)
    f(a, x...) = sum((x .- a).^2)
    register(model, :f, 1+nvar, f; autodiff = true)
    @NLobjective(model, Min, f(a, x...))
    optimize!(model)
    value.(x)
end
myfunc()

```

results in:

```julia
ERROR: Unexpected array NonlinearParameter[parameter[1] == 1.0, parameter[2] == 1.0, parameter[3] == 1.0] in nonlinear expression. Nonlinear expressions may contain only scalar expressions.

```

Thanks for your help,

Francis Gagnon

---

<div class="post-metadata">

**Author:** ![SteffenPL](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steffenpl/32/206270_2.png) [@SteffenPL](https://discourse.julialang.org/u/SteffenPL)\
**Post date:** [April 23, 2023, 5:16am UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/2 "2023-04-23T05:16:57Z")

</div>

Not the most elegant approach, but you could do this

```julia

using JuMP, Ipopt
function myfunc()
    model = Model(Ipopt.Optimizer)
    nvar = 3
    @variable(model, x[1:nvar])
    @NLparameter(model, a[i=1:nvar] == 1)
    f(z...) = sum((z[nvar+1:end] .- z[1:nvar]).^2)
    register(model, :f, 2*nvar, f; autodiff = true)
    @NLobjective(model, Min, f(a..., x...))
    optimize!(model)
    value.(x)
end
myfunc()

```

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [April 23, 2023, 3:49pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/3 "2023-04-23T15:49:26Z")

</div>

Thanks for the help, it is indeed a solution. I have multiple vector parameters, so yes it will be a bit messy. But it’s better than no solution!

---

<div class="post-metadata">

**Author:** ![SteffenPL](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steffenpl/32/206270_2.png) [@SteffenPL](https://discourse.julialang.org/u/SteffenPL)\
**Post date:** [April 23, 2023, 3:53pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/4 "2023-04-23T15:53:35Z")

</div>

Maybe you could use something like [API · ComponentArrays.jl](https://jonniedie.github.io/ComponentArrays.jl/stable/api/#ComponentArrays.getaxes-Tuple%7BComponentArray%7D) where you construct a `ComponentArray` with your inputs and then you get the indices via `getaxes` back, or you might even be able to directly access using labels inside the `f` function.

---

<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:** [April 23, 2023, 4:19pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/5 "2023-04-23T16:19:07Z")

</div>

If the parameters are used **exclusively** in the registered function, you have the option of hiding them from JuMP via a closure:

```julia
using JuMP, Ipopt
function myfunc()
    model = Model(Ipopt.Optimizer)
    nvar = 3
    @variable(model, x[1:nvar])
    a = zeros(nvar)
    f(x...) = sum((x .- a).^2)
    register(model, :f, nvar, f; autodiff = true)
    @NLobjective(model, Min, f(x...))
    optimize!(model)
    @show value.(x)

	a[1] = 10.0
    optimize!(model)
    @show value.(x)

end
myfunc()

```

In this case it’s on you to be aware of the subtleties around how to update the parameter outside the closure.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [April 23, 2023, 5:26pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/6 "2023-04-23T17:26:00Z")

</div>

> If the parameters are used **exclusively** in the registered function, you have the option of hiding them from JuMP via a closure:

This solution is still applicable if I use my parameters both in the objective function and the nonlinear constraint function (thus two separate registered functions) ?

---

<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:** [April 23, 2023, 5:41pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/7 "2023-04-23T17:41:29Z")

</div>

> This solution is still applicable if I use my parameters both in the objective function and the nonlinear constraint function (thus two separate registered functions) ?

Yes

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [April 23, 2023, 7:43pm UTC](https://discourse.julialang.org/t/nonlinear-objective-with-both-splatted-variable-and-vector-parameters/97791/8 "2023-04-23T19:43:57Z")

</div>

Great thanks! I’ll rely on your solution, it’s a bit tiddier than splating all the arguments.
