Callback for customized stopping rule based on Barrier dual bound for LP in Julia
AnsweredHi,
I am trying to create a callback function that allows me to stop a Barrier algorithm for a linear program prematurely based on some predefined threshold for the dual bound.
In a larger decomposition algorithm for two-stage stochastic programs, I have a current best objective of, say, 1000. A new candidate solution is sent to a potentially costly LP for evaluation. The evaluation only needs to be precise if the LP objective value is below the current best objective of 1000. Consequently, if the dual bound in the Barrier algorithm solving the LP exceeds 1000, I can be sure that I will not improve the current best with the given iterate. Hence, I want to stop the Barrier prematurely and still obtain the current primal bound and the corresponding primal and dual variable values.
I have been using the syntax provided for the Gurobi.jl wrapper in Julia: https://github.com/jump-dev/Gurobi.jl#callbacks
I have come up with this so far:
# builds a large-scale linear program for energy system optimization in JuMP
m = Model(Gurobi.Optimizer)
define_model!(m,dtr,maxhours=8760)
set_optimizer_attribute(m,"Method",2)
set_optimizer_attribute(m,"Crossover",0)
c = [] # container collecting all dual objective values (probably not very efficient)
thr = 1000 # this is the threshold as defined in a previous iteration of the decomp algorithm
function absolute_stopping_criterion(cb_data,cb_where)
objbound =Ref{Cdouble}()
Gurobi.GRBcbget(cb_data,cb_where,Gurobi.GRB_CB_BARRIER_DUALOBJ,objbound)
objbound = objbound[]
push!(c,objbound)
if maximum(c) > thr
Gurobi.GRBterminate(backend(m))
end
end
MOI.set(m,Gurobi.CallbackFunction(),absolute_stopping_criterion)
optimize!(m)
I get the following error once the threshold is reached:
ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{Nothing}}, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBriingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.Unive{Float64}}})rsalFallback{MathOptInterface.Utilities.Model{Float64}}})
Closest candidates are:
unsafe_convert(::Union{Type{Ptr{Nothing}}, Type{Ptr{Base.Libc.FILE}}}, ::Base.Libc.FILE) at ..\Local\Programs\Julia-1.7.2\share\julia\base\libc.jl:94 pData\Local\Programs\Julia-1.7.2\share\julia\
unsafe_convert(::Type{Ptr{T}}, ::SharedArrays.SharedArray{T}) where T at ..\Local\Programs\Julia-1.7.2\share\julia\stdlib\v1.7\SharedArrays\src\SharedArrays.jl:361 ta\Local\Programs\Julia-1.7.2\share\julia\std
unsafe_convert(::Type{Ptr{T}}, ::SharedArrays.SharedArray) where T at ..\Local\Programs\Julia-1.7.2\share\julia\stdlib\v1.7\SharedArrays\src\SharedArrays.jl:362
...
-
Edit: I managed to implement the custom stopping criterion and retrieve the associated primal objective value. But since the TerminationStatusCode is INTERRUPTED and not USERLIMIT I cannot retrieve variable values. How does one do that?
Best,
Felix
0 -
I have created a reproducible example here: Solver-specific callback for custom termination rule for LP Barrier using Gurobi and JuMP - Specific Domains / Optimization (Mathematical) - Julia Programming Language (julialang.org)
0 -
Hi Felix,
Thanks for the example.
Not sure why but this works in Python.
I will see if there's a workaround.Cheers,
David0 -
Hi David,
thank you very much.
Best
Felix
0 -
For reference see:
- Discourse (example and hack).
- Gurobi.jl#19 (to track fix)
Cheers,
David1 -
Thank you!
0
Please sign in to leave a comment.
Comments
6 comments