lanl-ansi / Juniper.jl

A JuMP-based Nonlinear Integer Program Solver
https://lanl-ansi.github.io/Juniper.jl/stable/
MIT License
179 stars 22 forks source link

Calling functions that returns macro doesnt work but using macro explictly works when describing constraint? #229

Closed DrVogt closed 2 years ago

DrVogt commented 2 years ago

Howdy,

using Juniper
using Ipopt
using JuMP
using LinearAlgebra # for the dot product
using Base.Threads
using Cbc

function test(w,x)

return sum(w[i]*x[i]^2 for i=1:5)
end

optimizer = Juniper.Optimizer
nl_solver= optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
mip_solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0, "threads"=>nthreads())
m = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver, "mip_solver"=>mip_solver))

v = [10,20,12,23,42]
w = [12,45,12,22,21]
@variable(m, x[1:5], Bin)

@objective(m, Max, dot(v,x))

#@NLconstraint(m, sum(w[i]*x[i]^2 for i=1:5) <=45)
@NLconstraint(m, test(w,x) <=45)

optimize!(m)

# retrieve the objective value, corresponding x values and the status
println(JuMP.value.(x))
println(JuMP.objective_value(m))
println(JuMP.termination_status(m))

If the macro is in the expression it works great; but when I define a function that returns that value it does not work? Any suggestions?

[ Info: Precompiling Juniper [2ddba703-00a4-53a7-87a5-e8b9971dde84]
[ Info: Precompiling Cbc [9961bab8-2fa3-5c5a-9d89-47fab24efd76]
┌ Warning: Function test automatically registered with 2 arguments.
│ 
│ Calling the function with a different number of arguments will result in an
│ error.
│ 
│ While you can safely ignore this warning, we recommend that you manually
│ register the function as follows:
│ ```Julia
│ model = Model()
│ register(model, :test, 2, test; autodiff = true)
│ ```
└ @ JuMP ~/.julia/packages/JuMP/Xrr7O/src/parse_nlp.jl:21
ERROR: LoadError: Unexpected array [12, 45, 12, 22, 21] in nonlinear expression. Nonlinear expressions may contain only scalar expressions.
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] _parse_NL_expr_runtime(::Model, ::Array{Int64,1}, ::Array{JuMP._Derivatives.NodeData,1}, ::Int64, ::Array{Float64,1}) at /Users/drvogt/.julia/packages/JuMP/Xrr7O/src/parse_nlp.jl:434
 [3] top-level scope at /Users/drvogt/.julia/packages/JuMP/Xrr7O/src/parse_nlp.jl:283
 [4] top-level scope at /Users/drvogt/.julia/packages/JuMP/Xrr7O/src/macros.jl:1953
 [5] top-level scope at /Users/drvogt/Dropbox/python/julia/mip.jl:34
 [6] include(::String) at ./client.jl:439
 [7] top-level scope at REPL[2]:1
in expression starting at /Users/drvogt/Dropbox/python/julia/mip.jl:34
odow commented 2 years ago

You cannot pass vectors to user-defined functions in JuMP.

Here is the relevant documentation: https://jump.dev/JuMP.jl/stable/manual/nlp/#User-defined-functions-with-vector-inputs

I'm going to close this issue because it is not a bug in Juniper. If you still have questions after reading the documentation, please post on the community forum, https://discourse.julialang.org/c/domain/opt/13, and we can continue the discussion there.