Sending a logistic function to Gurobi.jl with JuMP

JuMP and Gurobi seem to be able to accept nl functions via their new interface. But while I can see that Gurobi claims to accept :logistic as the “head” of a non-linear expression :logistic => GRB_OPCODE_LOGISTIC, I can’t figure out how to pass it in.

This works fine, but it’s not what I want

using Gurobi
using JuMP

m = Model(Gurobi.Optimizer)
@variable(m, 1 <= x <= 2)
@objective(m, Max, 1/(1+exp(-x)))
optimize!(m)

println(m)

Hi @votroto, you can do this:

julia> using Gurobi

julia> using JuMP

julia> model = Model(Gurobi.Optimizer)
Set parameter LicenseID to value 890341
A JuMP Model
├ solver: Gurobi
├ objective_sense: FEASIBILITY_SENSE
├ num_variables: 0
├ num_constraints: 0
└ Names registered in the model: none

julia> @variable(model, 1 <= x <= 2)
x

julia> grb_logistic(x) = NonlinearExpr(:logistic, x)
grb_logistic (generic function with 1 method)

julia> @objective(model, Max, grb_logistic(x))
logistic(x)

julia> optimize!(model)
Gurobi Optimizer version 12.0.1 build v12.0.1rc0 (mac64[x86] - Darwin 24.1.0 24B83)

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 0 rows, 3 columns and 0 nonzeros
Model fingerprint: 0xfa5cc70f
Model has 1 general nonlinear constraint (1 nonlinear terms)
Variable types: 3 continuous, 0 integer (0 binary)
Coefficient statistics:
  Matrix range     [0e+00, 0e+00]
  Objective range  [1e+00, 1e+00]
  Bounds range     [1e+00, 2e+00]
  RHS range        [0e+00, 0e+00]
Presolve model has 1 nlconstr
Added 1 variables to disaggregate expressions.
Presolve time: 0.00s
Presolved: 6 rows, 5 columns, 13 nonzeros
Presolved model has 1 nonlinear constraint(s)

Solving non-convex MINLP

Variable types: 5 continuous, 0 integer (0 binary)
Found heuristic solution: objective 0.8807971

Explored 1 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
Thread count was 8 (of 8 available processors)

Solution count 1: 0.880797 
No other solutions better than 0.880797

Optimal solution found (tolerance 1.00e-04)
Best objective 8.807970779779e-01, best bound 8.807970779779e-01, gap 0.0000%

User-callback calls 102, time in user-callback 0.00 sec

julia> value(x)
2.0

julia> objective_value(model)
0.8807970779778823

julia> 1 / (1 + exp(-2))
0.8807970779778823

that’s perfect, thanks!

1 Like