Add local and purgeable cuts in CPLEX

I am using CPLEX.jl and I add cuts in a callback with this syntax:

        con = @build_constraint(x <= 0)
        MOI.submit(myModel, MOI.UserCut(cb_data), con)

CPLEX library normally has several parameters when adding a cut that I would like to change (ex: the fact that the cut is purgeable or not, the fact that it is local to this branch or global to the whole tree).

To change these parameters, I would like to adapt the MOI.submit method. I tried to find its definition but the only one I found is the following one:

        function MOI.submit(
            model::Optimizer,
            cb::MOI.LazyConstraint{CallbackContext},
            f::MOI.ScalarAffineFunction{Float64},
            s::Union{
                MOI.LessThan{Float64},
                MOI.GreaterThan{Float64},
                MOI.EqualTo{Float64},
            },
        )

Unfortunately, this is not the method called when I use MOI.submit since the arguments types and number do not match. I tried to copy/paste it anyway just to be sure. I named the new method “mySubmit” but as expected, when I try to use it I get an error:

            ERROR: MethodError: no method matching mySubmit(::Model, ::MathOptInterface.LazyConstraint{CPLEX.CallbackContext}, ::ScalarConstraint{AffExpr, MathOptInterface.LessThan{Float64}})
            Closest candidates are:
              mySubmit(::CPLEX.Optimizer, ::MathOptInterface.LazyConstraint{CPLEX.CallbackContext}, ::MathOptInterface.ScalarAffineFunction{Float64}, ::Union{MathOptInterface.EqualTo{Float64}, MathOptInterface.GreaterThan{Float64}, MathOptInterface.LessThan{Float64}}) at /home/zach/Test/dummy_cb_ex.jl:79

Two of the arguments do not have the correct type:

  • the first one is “Model” instead of “CPLEX.Optimizer”;
  • the third one which defines the constraint.

Do you know where I can find the definition of the method called when I use MOI.submit? If it is the one I found, could you tell me why it does not work? I am a bit lost here…

Without answering your specific question, you can generally use the Julia macro @which before your function call to return this information:
https://docs.julialang.org/en/v1/stdlib/InteractiveUtils/#InteractiveUtils.@which

More specific to your question, each solver wrapper package (like CPLEX.jl) implements the MOI API. The MOI.submit for CPLEX here is the one you found?

1 Like

For the discrepancy in the first argument, notice that the example in the CPLEX.jl README uses direct_model:

model = direct_model(CPLEX.Optimizer())

For the second:

the error tells you your argument is of the type above, but it might need to be

Thank you for your answers!
With @which I was able to find exactly the function called. In the end I had to adapt 10 functions to make it work, but it works!

2 Likes

Glad you got it working. You could also just use the solver-specific CPLEX callback and the C API directly. No need to modify a bunch of methods in MOI.

1 Like