CPLEX.jl is a wrapper for the IBM® ILOG® CPLEX® Optimization Studio.
CPLEX.jl has two components:
The C API can be accessed via CPLEX.CPXxx
functions, where the names and arguments are identical to the C API. See the CPLEX documentation for details.
This wrapper is maintained by the JuMP community and is not officially supported by IBM. However, we thank IBM for providing us with a CPLEX license to test CPLEX.jl
on GitHub. If you are a commercial customer interested in official support for CPLEX in Julia, let them know.
If you need help, please ask a question on the JuMP community forum.
If you have a reproducible example of a bug, please open a GitHub issue.
CPLEX.jl
is licensed under the MIT License.
The underlying solver is a closed-source commercial product for which you must purchase a license.
Free CPLEX licenses are available for academics and students.
CPLEX.jl requires CPLEX version 12.10, 20.1, or 22.1.
First, obtain a license of CPLEX and install CPLEX solver, following the instructions on IBM's website.
Once installed, set the CPLEX_STUDIO_BINARIES
environment variable as appropriate and run Pkg.add("CPLEX")
. For example:
# On Windows, this might be: ENV["CPLEX_STUDIO_BINARIES"] = "C:\\Program Files\\CPLEX_Studio1210\\cplex\\bin\\x86-64_win\\" # On OSX, this might be: ENV["CPLEX_STUDIO_BINARIES"] = "/Applications/CPLEX_Studio1210/cplex/bin/x86-64_osx/" # On Unix, this might be: ENV["CPLEX_STUDIO_BINARIES"] = "/opt/CPLEX_Studio1210/cplex/bin/x86-64_linux/" import Pkg Pkg.add("CPLEX")
!!! note The exact path may differ. Check which folder you installed CPLEX in, and update the path accordingly.
Use CPLEX.jl
with JuMP as follows:
using JuMP, CPLEX model = Model(CPLEX.Optimizer) set_attribute(model, "CPX_PARAM_EPINT", 1e-8)
The CPLEX optimizer supports the following constraints and attributes.
List of supported objective functions:
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}
MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}}
MOI.ObjectiveFunction{MOI.VariableIndex}
MOI.ObjectiveFunction{MOI.VectorAffineFunction{Float64}}
List of supported variable types:
List of supported constraint types:
MOI.ScalarAffineFunction{Float64}
in MOI.EqualTo{Float64}
MOI.ScalarAffineFunction{Float64}
in MOI.GreaterThan{Float64}
MOI.ScalarAffineFunction{Float64}
in MOI.LessThan{Float64}
MOI.ScalarQuadraticFunction{Float64}
in MOI.GreaterThan{Float64}
MOI.ScalarQuadraticFunction{Float64}
in MOI.LessThan{Float64}
MOI.VariableIndex
in MOI.EqualTo{Float64}
MOI.VariableIndex
in MOI.GreaterThan{Float64}
MOI.VariableIndex
in MOI.Integer
MOI.VariableIndex
in MOI.Interval{Float64}
MOI.VariableIndex
in MOI.LessThan{Float64}
MOI.VariableIndex
in MOI.Semicontinuous{Float64}
MOI.VariableIndex
in MOI.Semiinteger{Float64}
MOI.VariableIndex
in MOI.ZeroOne
MOI.VectorOfVariables
in MOI.SOS1{Float64}
MOI.VectorOfVariables
in MOI.SOS2{Float64}
MOI.VectorOfVariables
in MOI.SecondOrderCone
MOI.VectorAffineFunction
in MOI.Indicator
List of supported model attributes:
MOI.ConflictStatus()
MOI.HeuristicCallback()
MOI.LazyConstraintCallback()
MOI.Name()
MOI.ObjectiveSense()
MOI.UserCutCallback()
Options match those of the C API in the CPLEX documentation.
Set options using JuMP.set_attribute
:
using JuMP, CPLEX model = Model(CPLEX.Optimizer) set_attribute(model, "CPX_PARAM_EPINT", 1e-8)
CPLEX.jl provides a solver-specific callback to CPLEX:
using JuMP, CPLEX, Test model = direct_model(CPLEX.Optimizer()) set_silent(model) # This is very, very important!!! Only use callbacks in single-threaded mode. MOI.set(model, MOI.NumberOfThreads(), 1) @variable(model, 0 <= x <= 2.5, Int) @variable(model, 0 <= y <= 2.5, Int) @objective(model, Max, y) cb_calls = Clong[] function my_callback_function(cb_data::CPLEX.CallbackContext, context_id::Clong) # You can reference variables outside the function as normal push!(cb_calls, context_id) # You can select where the callback is run if context_id != CPX_CALLBACKCONTEXT_CANDIDATE return end ispoint_p = Ref{Cint}() ret = CPXcallbackcandidateispoint(cb_data, ispoint_p) if ret != 0 || ispoint_p[] == 0 return # No candidate point available or error end # You can query CALLBACKINFO items valueP = Ref{Cdouble}() ret = CPXcallbackgetinfodbl(cb_data, CPXCALLBACKINFO_BEST_BND, valueP) @info "Best bound is currently: $(valueP[])" # As well as any other C API x_p = Vector{Cdouble}(undef, 2) obj_p = Ref{Cdouble}() ret = CPXcallbackgetincumbent(cb_data, x_p, 0, 1, obj_p) if ret == 0 @info "Objective incumbent is: $(obj_p[])" @info "Incumbent solution is: $(x_p)" # Use CPLEX.column to map between variable references and the 1-based # column. x_col = CPLEX.column(cb_data, index(x)) @info "x = $(x_p[x_col])" else # Unable to query incumbent. end # Before querying `callback_value`, you must call: CPLEX.load_callback_variable_primal(cb_data, context_id) x_val = callback_value(cb_data, x) y_val = callback_value(cb_data, y) # You can submit solver-independent MathOptInterface attributes such as # lazy constraints, user-cuts, and heuristic solutions. if y_val - x_val > 1 + 1e-6 con = @build_constraint(y - x <= 1) MOI.submit(model, MOI.LazyConstraint(cb_data), con) elseif y_val + x_val > 3 + 1e-6 con = @build_constraint(y + x <= 3) MOI.submit(model, MOI.LazyConstraint(cb_data), con) end end MOI.set(model, CPLEX.CallbackFunction(), my_callback_function) optimize!(model) @test termination_status(model) == MOI.OPTIMAL @test primal_status(model) == MOI.FEASIBLE_POINT @test value(x) == 1 @test value(y) == 2Annotations for automatic Benders' decomposition
Here is an example of using the annotation feature for automatic Benders' decomposition:
using JuMP, CPLEX function add_annotation( model::JuMP.Model, variable_classification::Dict; all_variables::Bool = true, ) num_variables = sum(length(it) for it in values(variable_classification)) if all_variables @assert num_variables == JuMP.num_variables(model) end indices, annotations = CPXINT[], CPXLONG[] for (key, value) in variable_classification for variable_ref in value push!(indices, variable_ref.index.value - 1) push!(annotations, CPX_BENDERS_MASTERVALUE + key) end end cplex = backend(model) index_p = Ref{CPXINT}() CPXnewlongannotation( cplex.env, cplex.lp, CPX_BENDERS_ANNOTATION, CPX_BENDERS_MASTERVALUE, ) CPXgetlongannotationindex( cplex.env, cplex.lp, CPX_BENDERS_ANNOTATION, index_p, ) CPXsetlongannotations( cplex.env, cplex.lp, index_p[], CPX_ANNOTATIONOBJ_COL, length(indices), indices, annotations, ) return end # Problem function illustrate_full_annotation() c_1, c_2 = [1, 4], [2, 3] dim_x, dim_y = length(c_1), length(c_2) b = [-2; -3] A_1, A_2 = [1 -3; -1 -3], [1 -2; -1 -1] model = JuMP.direct_model(CPLEX.Optimizer()) set_optimizer_attribute(model, "CPXPARAM_Benders_Strategy", 1) @variable(model, x[1:dim_x] >= 0, Bin) @variable(model, y[1:dim_y] >= 0) variable_classification = Dict(0 => [x[1], x[2]], 1 => [y[1], y[2]]) @constraint(model, A_2 * y + A_1 * x .<= b) @objective(model, Min, c_1' * x + c_2' * y) add_annotation(model, variable_classification) optimize!(model) x_optimal = value.(x) y_optimal = value.(y) println("x: $(x_optimal), y: $(y_optimal)") end function illustrate_partial_annotation() c_1, c_2 = [1, 4], [2, 3] dim_x, dim_y = length(c_1), length(c_2) b = [-2; -3] A_1, A_2 = [1 -3; -1 -3], [1 -2; -1 -1] model = JuMP.direct_model(CPLEX.Optimizer()) # Note that the "CPXPARAM_Benders_Strategy" has to be set to 2 if partial # annotation is provided. If "CPXPARAM_Benders_Strategy" is set to 1, then # the following error will be thrown: # `CPLEX Error 2002: Invalid Benders decomposition.` set_optimizer_attribute(model, "CPXPARAM_Benders_Strategy", 2) @variable(model, x[1:dim_x] >= 0, Bin) @variable(model, y[1:dim_y] >= 0) variable_classification = Dict(0 => [x[1]], 1 => [y[1], y[2]]) @constraint(model, A_2 * y + A_1 * x .<= b) @objective(model, Min, c_1' * x + c_2' * y) add_annotation(model, variable_classification; all_variables = false) optimize!(model) x_optimal = value.(x) y_optimal = value.(y) println("x: $(x_optimal), y: $(y_optimal)") end
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4