# Problem with cost function in JuMP

Hello everyone,

I am interested in the following optimization problem that I would like to solve with JuMP:

\begin{split} \min_{x \in \mathbb{R}^n} & (z^Tx)^2 - \log(b^T x[l:\mbox{end}])\\ \mbox{ subject to }& x[l:\mbox{end}] \geq 0 \end{split}

with k<n, b \in \mathbb{R}^k and z \in \mathbb{R}^n. x[l:\mbox{end}] denotes the last l components of the vector x.

I am not sure of the way to provide parameters to a user-defined function. Also, I got an error saying that I should use only scalar expressions which seems to be the case

Here is my code:

Code for the cost function

function _cost(x, wquad, w∂,p)
J = 0.0
nx = length(x)
for i=1:Ne

if p==0
J += -log(w∂[1,i]*x[end])
else
J += -log(sum(w∂[j,i]*x[end-(p+2)+j] for j=1:p+2))
end
end
J *=  (1/Ne)
return J
end


Rest of the code for the optimization

p=2
wq = randn(32,200)
w∂ = randn(4,200)

Ne = 200
nx = size(wq,1)
nlog = size(w∂,1)

# Create the model
model = Model(Ipopt.Optimizer)

# Create variable x
@variable(model, x[1:nx], start = 0.001)

@NLparameter(model, p_order== p)
@NLparameter(model, z[i = 1:nx, j = 1:Ne] == max(wq[i,j], 0.001))
@NLparameter(model, b[i = 1:nlog, j = 1:Ne] == max(w∂[i,j], 0.001))

# Define cost function
cost(x...) = _cost(x, z, b, p_order)
register(model, :cost, 1, cost, autodiff=true)

# Set lower bound on x
for i in nx-nlog:nx
set_lower_bound(x[i], 0.0)
end

@NLobjective(model, Min, cost(x))

@time optimize!(model)


Code return message

Unexpected array VariableRef[x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x] in nonlinear expression. Nonlinear expressions may contain only scalar expressions.

Stacktrace:
 error(::String) at ./error.jl:33
 _parse_NL_expr_runtime(::Model, ::Array{VariableRef,1}, ::Array{JuMP._Derivatives.NodeData,1}, ::Int64, ::Array{Float64,1}) at /Users/me/.julia/packages/JuMP/CZ8vV/src/parse_nlp.jl:207
 top-level scope at /Users/me/.julia/packages/JuMP/CZ8vV/src/parse_nlp.jl:82
 top-level scope at /Users/me/.julia/packages/JuMP/CZ8vV/src/macros.jl:1274
 top-level scope at In:28


If you do this, then (I think), x will passed as x, x as z, x as b and x[4:end] as p_order. Is that what you want?

1 Like

Why not just write it out in the macro?

@NLobjective(model, Min, sum(z[i] * x[i] for i=1:N)^2 - log(sum(b[i] * x[i] for i=l:N)))

1 Like

Thanks I think that’s the way to go. I’ve just found easier to write functions called by others functions.