forked from jump-dev/JuMP.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcallbacks.jl
88 lines (77 loc) · 3.3 KB
/
callbacks.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#############################################################################
# JuMP
# An algebraic modeling language for Julia
# See https://github.com/jump-dev/JuMP.jl
#############################################################################
"""
callback_node_status(cb_data, model::Model)
Return an [`MOI.CallbackNodeStatusCode`](@ref) enum, indicating if the current
primal solution available from [`callback_value`](@ref) is integer feasible.
"""
function callback_node_status(cb_data, model::Model)
# TODO(odow):
# MOI defines `is_set_by_optimize(::CallbackNodeStatus) = true`.
# This causes problems for JuMP because it checks the termination_status to
# see if optimize! has been called. Solutions are:
# 1) defining is_set_by_optimize = false
# 2) adding a flag to JuMP to store whether it is in a callback
# 3) adding IN_OPTIMIZE to termination_status for callbacks
# Once this is resolved, we can replace the current function with:
# MOI.get(model, MOI.CallbackNodeStatus(cb_data))
return MOI.get(backend(model), MOI.CallbackNodeStatus(cb_data))
end
"""
callback_value(cb_data, x::VariableRef)
Return the primal solution of a variable inside a callback.
`cb_data` is the argument to the callback function, and the type is dependent on
the solver.
"""
function callback_value(cb_data, x::VariableRef)
# TODO(odow):
# MOI defines `is_set_by_optimize(::CallbackVariablePrimal) = true`.
# This causes problems for JuMP because it checks the termination_status to
# see if optimize! has been called. Solutions are:
# 1) defining is_set_by_optimize = false
# 2) adding a flag to JuMP to store whether it is in a callback
# 3) adding IN_OPTIMIZE to termination_status for callbacks
# Once this is resolved, we can replace the current function with:
# MOI.get(owner_model(x), MOI.CallbackVariablePrimal(cb_data), x)
return MOI.get(
backend(owner_model(x)),
MOI.CallbackVariablePrimal(cb_data),
index(x),
)
end
"""
callback_value(cb_data, expr::Union{GenericAffExpr, GenericQuadExpr})
Return the primal solution of an affine or quadratic expression inside a callback by getting
the value for each variable appearing in the expression.
`cb_data` is the argument to the callback function, and the type is dependent on
the solver.
"""
function callback_value(cb_data, expr::Union{GenericAffExpr,GenericQuadExpr})
return value(expr, v -> callback_value(cb_data, v))
end
function MOI.submit(model::Model, cb::MOI.LazyConstraint, con::ScalarConstraint)
return MOI.submit(backend(model), cb, moi_function(con.func), con.set)
end
function MOI.submit(model::Model, cb::MOI.UserCut, con::ScalarConstraint)
return MOI.submit(backend(model), cb, moi_function(con.func), con.set)
end
function MOI.submit(
model::Model,
cb::MOI.HeuristicSolution,
variables::Vector{VariableRef},
values::Vector{<:Real},
)
return MOI.submit(
backend(model),
cb,
index.(variables),
convert(Vector{Float64}, values),
)
end