Skip to content

DNMY: add solver-independent(-ish) callbacks #670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/MathOptInterface.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
VERSION < v"0.7.0-beta2.199" && __precompile__()
module MathOptInterface

using Compat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed anymore


"""
ModelLike

Expand Down Expand Up @@ -117,6 +119,7 @@ include("constraints.jl")
include("modifications.jl")
include("variables.jl")
include("nlp.jl")
include("callbacks.jl")

# submodules
include("Utilities/Utilities.jl") # MOI.Utilities
Expand Down
77 changes: 77 additions & 0 deletions src/callbacks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Callbacks(; lazy = nothing, heuristic = nothing)

Set MIP-based callbacks. Two basic types are offered: `lazy` and `heuristic`.

### The lazy callback

The `lazy` callback can be used to add *lazy* constraints which are added
on-demand at integer nodes in the branch and bound tree.

Points to consider are:

- The lazy constraint callback *may* be called when the solver has an integer
primal solution.
- You can only access the primal solution through `VariablePrimal`. For example,
`ConstraintDual` etc will not work.
- The optimal solution will satisfy all lazy constraints that could *possibly*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean? What are the constraints that could possibly have been added and how do they differ from the constraints actually returned?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Poor wording on my part. It should just say all constraints that have been added. I'll hold off changing until we have a consensus on the larger issue of whether we want these in the first place.

have been added.

See also [`add_lazy_constraint`](@ref).

### The heuristic callback

The `heuristic` callback can be used to provide the solver with heuristically
obtained integer-feasible solutions at fractional nodes in the branch and bound
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What attributes can be queried in the heuristic callback?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only VariablePrimal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a regression from MPB and isn't sufficient to cover Pajarito: https://github.com/JuliaOpt/Pajarito.jl/blob/027cfbf882b4a1ae78f45fb11a6e51c58468a20f/src/conic_algorithm.jl#L1446 (this is from the lazy callback)

tree.

Points to consider are:

- The heuristic callback *may* be called when the solver has a fractional (i.e.,
non-integer) solution.
- The solver may silently reject the provided solution.
- Some solvers require a complete solution, others only partial solutions. It's
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the solution have to satisfy all constraints in the model?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, see above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a solution does not satisfy constraints, is it guaranteed to be rejected?

up to you to provide the appropriate one. If in doubt, give a complete
solution.

See also [`add_heuristic_solution`](@ref).
"""
struct Callbacks <: AbstractModelAttribute
lazy_callback::Union{Function, Nothing}
heuristic_callback::Union{Function, Nothing}
function Callbacks(; lazy = nothing, heuristic = nothing)
return new(lazy, heuristic)
end
end

"""
add_lazy_constraint(
model::ModelLike, cb_data, func::AbstractFunction, set::AbstractSet)

Add a lazy constraint `func`-in-`set` to `model`.

This can be called only from a lazy callback set by the attribute `Callbacks()`.

`cb_data` is a solver-specific callback type that is passed as the argument to
the lazy callback.
"""
function add_lazy_constraint(model, cb_data, func, set)
error("add_lazy_constraint is not supported by this solver.")
end

"""
add_heuristic_solution(
model::ModelLike, cb_data, sol::Dict{VariableIndex, Float64})

Provide the heuristic solution given by the variable-value mapping of `sol` to
`model`.

This can be called only from a heuristic callback set by the attribute
`Callbacks()`.

`cb_data` is a solver-specific callback type that is passed as the argument to
the heuristic callback.
"""
function add_heuristic_solution(model, cb_data, sol)
error("add_heuristic_solution is not supported by this solver.")
end