Skip to content

Commit

Permalink
Add callback example to README (#271)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Jul 15, 2024
1 parent a7c69de commit a965516
Showing 1 changed file with 48 additions and 4 deletions.
52 changes: 48 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,54 @@ default, `logfile = ""` (console).

## Callbacks

Solver specific and solver independent callbacks are working in
[MathOptInterface](https://github.com/jump-dev/MathOptInterface.jl) and,
consequently, in [JuMP](https://github.com/jump-dev/JuMP.jl). However, the
current implementation should be considered experimental.
Here is an example using Xpress's solver-specific callbacks.

```julia
using JuMP, Xpress, Test

model = direct_model(Xpress.Optimizer())
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)
function my_callback_function(cb_data)
prob = cb_data.model
p_value = Ref{Cint}(0)
ret = Xpress.Lib.XPRSgetintattrib(prob, Xpress.Lib.XPRS_MIPINFEAS, p_value)
if p_value[] > 0
return # There are integer infeasibilities. The solution is fractional.
end
p_obj, p_bound = Ref{Cdouble}(), Ref{Cdouble}()
Xpress.Lib.XPRSgetdblattrib(prob, Xpress.Lib.XPRS_MIPBESTOBJVAL, p_obj)
Xpress.Lib.XPRSgetdblattrib(prob, Xpress.Lib.XPRS_BESTBOUND, p_bound)
rel_gap = abs((p_obj[] - p_bound[]) / p_obj[])
@info "Relative gap = $rel_gap"
# Before querying `callback_value`, you must call:
Xpress.get_cb_solution(unsafe_backend(model), cb_data.model)
x_val = callback_value(cb_data, x)
y_val = callback_value(cb_data, y)
# You can submit solver-independent MathOptInterface attributes such as
# lazy constraints, user-cuts, and heuristic solutions.
if y_val - x_val > 1 + 1e-6
con = @build_constraint(y - x <= 1)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
elseif y_val + x_val > 3 + 1e-6
con = @build_constraint(y + x <= 3)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
if rand() < 0.1
# You can terminate the callback as follows:
Xpress.Lib.XPRSinterrupt(cb_data.model, 1234)
end
return
end
set_attribute(model, Xpress.CallbackFunction(), my_callback_function)
set_attribute(model, "HEUREMPHASIS", 0)
optimize!(model)
@test termination_status(model) == MOI.OPTIMAL
@test primal_status(model) == MOI.FEASIBLE_POINT
@test value(x) == 1
@test value(y) == 2
```

## Environment variables

Expand Down

0 comments on commit a965516

Please sign in to comment.