Skip to content
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

Add callbacks functionality #177

Open
trathi05 opened this issue May 19, 2022 · 5 comments
Open

Add callbacks functionality #177

trathi05 opened this issue May 19, 2022 · 5 comments

Comments

@trathi05
Copy link
Contributor

Right now, adding callbacks throws an error. For example:

using JuMP, BilevelJuMP, Gurobi

model = BilevelModel(Gurobi.Optimizer, mode = BilevelJuMP.SOS1Mode())

@variable(Lower(model), x)
@variable(Upper(model), y, Int)

@objective(Upper(model), Min,  y)
@constraints(Upper(model), begin
    x <= 5
    y <= 8
    y >= 0
end)

@objective(Lower(model), Min, -x)
@constraints(Lower(model), begin
     x +  y <= 8
    4x +  y >= 8
    2x +  y <= 13
    2x - 7y <= 0
end)

function my_callback_function(cb_data)
    y_val = callback_value(cb_data, y)
    con = @build_constraint(y<= floor(y_val))
    println("Adding $(con)")
    MOI.submit(model, MOI.UserCut(cb_data), con)
end

MOI.set(model, MOI.UserCutCallback(), my_callback_function)

The following error is thrown:

ERROR: Callbacks are not available in BilevelJuMP Models

I will be happy to work on a PR for this as and when I get time. However, it will take me some time to familiarize myself with the internals of BilevelJuMP. Also, what will be a good place to start, probably like some reference on how it could possibly be done? I guess one place I could look at it is the implementation of callbacks in JuMP itself.

@odow
Copy link
Collaborator

odow commented May 19, 2022

I don't think there is a good way of doing this, because the y variable that you see is not part of the model that is actually solved.

You really need to add a callback to the reformulated problem, and that seems difficult.

@trathi05
Copy link
Contributor Author

... because the `y' variable that you see is not part of the model that is actually solved.

Oh, I see. Well, then it seems like a difficult problem. Anyway, I'll keep the issue open for now and see if @joaquimg has any suggestions as well. Thanks.

@joaquimg
Copy link
Owner

As @odow said, the model is reformulated which adds extra difficulty to the process.
First,
Adding callbacks to the lower level will be very hard because that will add dual variables to the kkt conditions. So I don't think we should go there.
However,
If you want to add cuts to the upper level, there is hope.
BilevelJuMP keeps maps from the original model to the reformulated one. so you can go from y to the internal variable that represents it. You can see those maps in the functions for querying solutions that start from y and go to the internal variable.
We would have to overload MOI.submit so that we convert variable to the internal references (the same ones from the solution query) and add that new constraint to the solver.

@joaquimg
Copy link
Owner

You should certainly be very familiar with the MOI and JuMP callbacks before trying to implement them in BilevelJuMP.

@trathi05
Copy link
Contributor Author

If you want to add cuts to the upper level, there is hope.

That's what I was hoping to achieve with my model. So, it's good to know it's possible to do, albeit difficult.

You can see those maps in the functions for querying solutions that start from y and go to the internal variable.

Thanks for the direction here. I will see if I can figure out the connection here.

You should certainly be very familiar with the MOI and JuMP callbacks before trying to implement them in BilevelJuMP.

Good to know this. I will probably take some time to review the MOI/JuMP callbacks then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants