Manual
This package only works for optimization models that can be written in the conic-form.
Conic Duality
Conic duality is the starting point for MOI's duality conventions. When all functions are affine (or coordinate projections), and all constraint sets are closed convex cones, the model may be called a conic optimization problem. For conic-form minimization problems, the primal is:
and the dual is:
where each $\mathcal{C}_i$ is a closed convex cone and $\mathcal{C}_i^*$ is its dual cone.
For conic-form maximization problems, the primal is:
and the dual is:
A linear inequality constraint $a^T x + b \ge c$ should be interpreted as $a^T x + b - c \in \mathbb{R}_+$, and similarly $a^T x + b \le c$ should be interpreted as $a^T x + b - c \in \mathbb{R}_-$. Variable-wise constraints should be interpreted as affine constraints with the appropriate identity mapping in place of $A_i$.
For the special case of minimization LPs, the MOI primal form can be stated as
By applying the stated transformations to conic form, taking the dual, and transforming back into linear inequality form, one obtains the following dual:
For maximization LPs, the MOI primal form can be stated as:
and similarly, the dual is:
Supported constraints
This is the list of supported Function-in-Set
constraints of the package. If you try to dualize a constraint not listed here, it will return an unsupported error.
MOI Function | MOI Set |
---|---|
SingleVariable | GreaterThan |
SingleVariable | LessThan |
SingleVariable | EqualTo |
ScalarAffineFunction | GreaterThan |
ScalarAffineFunction | LessThan |
ScalarAffineFunction | EqualTo |
VectorOfVariables | Nonnegatives |
VectorOfVariables | Nonpositives |
VectorOfVariables | Zeros |
VectorOfVariables | SecondOrderCone |
VectorOfVariables | RotatedSecondOrderCone |
VectorOfVariables | PositiveSemidefiniteConeTriangle |
VectorOfVariables | ExponentialCone |
VectorOfVariables | DualExponentialCone |
VectorOfVariables | PowerCone |
VectorOfVariables | DualPowerCone |
VectorAffineFunction | Nonnegatives |
VectorAffineFunction | Nonpositives |
VectorAffineFunction | Zeros |
VectorAffineFunction | SecondOrderCone |
VectorAffineFunction | RotatedSecondOrderCone |
VectorAffineFunction | PositiveSemidefiniteConeTriangle |
VectorAffineFunction | ExponentialCone |
VectorAffineFunction | DualExponentialCone |
VectorAffineFunction | PowerCone |
VectorAffineFunction | DualPowerCone |
Note that some of MOI constraints can be bridged, see Bridges, to constraints in this list.
Supported objective functions
MOI Function |
---|
SingleVariable |
ScalarAffineFunction |
Dualize a model
Dualization.dualize
โ Function.dualize(args...; kwargs...)
The dualize
function works in three different ways. The user can provide:
- A
MathOptInterface.ModelLike
The function will return a DualProblem
struct that has the dualized model and PrimalDualMap{Float64}
for users to identify the links between primal and dual model.
A
MathOptInterface.ModelLike
and aDualProblem{T}
A
JuMP.Model
The function will return a JuMP model with the dual representation of the problem.
- A
JuMP.Model
and an optimizer factory
The function will return a JuMP model with the dual representation of the problem with the OptimizerFactory
attached. The OptimizerFactory
is the solver and its key arguments that users provide in JuMP models, i.e. with_optimizer(GLPK.Optimizer)
.
On each of these methods, the user can provide the keyword argument dual_names
. dual_names
must be a DualNames
struct. It allows users to set more intuitive names for the dual variables and dual constraints created.
DualOptimizer
You can solve a primal problem by using its dual formulation using the DualOptimizer
.
Dualization.DualOptimizer
โ Type.DualOptimizer(dual_optimizer::OT) where {OT <: MOI.ModelLike}
The DualOptimizer finds the solution for a problem solving its dual representation. It builds the dual model and solve it using the dual_optimizer
as solver.
The user can define the model providing the DualOptimizer
and the solver of its choice
julia> using Dualization, JuMP, GLPK
julia> model = Model(with_optimizer(DualOptimizer, GLPK.Optimizer()))
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: Dual model with GLPK attached
Adding new sets
Dualization.jl can automatically dualize models with custom sets. To do this, the user needs to define the set and its dual set and provide the functions:
supported_constraint
dual_set
If the custom set has some special scalar product (see the link), the user also needs to provide a set_dot
function.
For example, let us define a fake cone and its dual, the fake dual cone. We will write a JuMP model with the fake cone and dualize it.
using Dualization, JuMP, MathOptInterface, LinearAlgebra
# Rename MathOptInterface to simplify the code
const MOI = MathOptInterface
# Define the custom cone and its dual
struct FakeCone <: MOI.AbstractVectorSet
dimension::Int
end
struct FakeDualCone <: MOI.AbstractVectorSet
dimension::Int
end
# Define a model with your FakeCone
model = Model()
@variable(model, x[1:3])
@constraint(model, con, x in FakeCone(3)) # Note that the constraint name is "con"
@objective(model, Min, sum(x))
The resulting JuMP model is
Now in order to dualize we must overload the methods as described above.
# Overload the methods dual_set and supported_constraints
Dualization.dual_set(s::FakeCone) = FakeDualCone(MOI.dimension(s))
Dualization.supported_constraint(::Type{MOI.VectorOfVariables}, ::Type{<:FakeCone}) = true
# If your set has some specific scalar product you also need to define a new set_dot function
# Our FakeCone has this weird scalar product
MOI.Utilities.set_dot(x::Vector, y::Vector, set::FakeCone) = 2dot(x, y)
# Dualize the model
dual_model = dualize(model)
The resulting dual model is
If the model has constraints that are MOI.VectorAffineFunction
model = Model()
@variable(model, x[1:3])
@constraint(model, con, x + 3 in FakeCone(3))
@objective(model, Min, sum(x))
the user only needs to extend the supported_constraints
function.
# Overload the supported_constraints for VectorAffineFunction
Dualization.supported_constraint(::Type{<:MOI.VectorAffineFunction}, ::Type{<:FakeCone}) = true
# Dualize the model
dual_model = dualize(model)
The resulting dual model is