メインコンテンツへスキップ

Does callbacks affect to the selection of algorithm?

回答済み

コメント

2件のコメント

  • Byron Tasseff
    • Gurobi Staff

    Hi Taehyeon,

    When using a lazy constraint callback, Gurobi requires setting LazyConstraints=1. As described in the documentation for this parameter, this setting tells Gurobi to avoid model reductions and transformations that are incompatible with lazy constraints. In particular, as discussed in the article “What are dual reductions?”, this setting will disable dual reductions, which are often quite helpful. The disabling of these presolve reductions is the reason the presolved model differs and why the algorithm ultimately takes a different solution path.

    Before proceeding, I would like to note that the Julia/JuMP interface in Gurobi.jl is not developed or officially supported by us. That said, in the Gurobi.jl code here, you'll find that LazyConstraints=1 is automatically (and correctly) configured when a JuMP/MathOptInterface lazy constraint callback is set. In your Gurobi logging output, you should see:

    Non-default parameters:
    LazyConstraints  1

    In your example, however, I notice that your callback function is purely informational. It is not being used to reduce the feasible set of the problem, which is typically when lazy constraint callbacks are employed. You may find this example in JuMP's documentation for a Gurobi solver-dependent callback more applicable to your use case. Assuming you are interested in logging new incumbents (and not all integer-feasible solutions that are encountered, as in your current callback), I believe you could instead write your callback function using something similar to the following:

    ...
    import Gurobi
    ...
    
    function incumbent_callback(cb_data, cb_where::Cint)
       # Only log when a new incumbent solution is found
       if cb_where != Gurobi.GRB_CB_MIPSOL
           return
       end
    
       # Before querying callback_value, load primal variable values
       Gurobi.load_callback_variable_primal(cb_data, cb_where)
    
       obj_value = callback_value(cb_data, obj_oil)
       elapsed = time() - t0
    
       open(log_file, "a") do f
           @printf(f, "%.6f,%.6f\n", elapsed, obj_value)
       end
    
       return
    end

    This callback can then be set via

    set_attribute(model, Gurobi.CallbackFunction(), incumbent_callback)

    With this callback, there would be no need to set LazyConstraints=1 since lazy constraints are not being used. The solution paths should be identical with and without such a callback. You can review the Callback Codes section of our documentation if your application requires checking different cb_where values.

    I hope this helps! Please let me know if you have additional questions related to Gurobi, and I'll try my best to answer them. If you have JuMP-specific questions, I'd highly recommend asking in the JuMP community forum.

    1
  • Taehyeon Kwon
    • First Comment
    • First Question

    I sincerely appreciate your insightful answer. Understanding the impact of callbacks on the solver's path is crucial for me. Your explanation was both clear and comprehensive. Thank you!

    1

サインインしてコメントを残してください。