Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name = "Dualization"
uuid = "191a621a-6537-11e9-281d-650236a99e60"
authors = ["guilhermebodin <guilherme.b.moraes@gmail.com>"]
version = "0.3.5"
version = "0.4.0"

[deps]
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"

[compat]
JuMP = "0.21"
MathOptInterface = "0.9"
JuMP = "0.22"
MathOptInterface = "0.10"
julia = "1"

[extras]
Expand Down
8 changes: 4 additions & 4 deletions docs/src/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ a constraint not listed here, it will return an unsupported error.

| MOI Function | MOI Set |
|:-------|:---------------|
| `SingleVariable` | `GreaterThan` |
| `SingleVariable` | `LessThan` |
| `SingleVariable` | `EqualTo` |
| `VariableIndex` | `GreaterThan` |
| `VariableIndex` | `LessThan` |
| `VariableIndex` | `EqualTo` |
| `ScalarAffineFunction` | `GreaterThan` |
| `ScalarAffineFunction` | `LessThan` |
| `ScalarAffineFunction` | `EqualTo` |
Expand Down Expand Up @@ -143,7 +143,7 @@ Note that some of MOI constraints can be bridged, see [Bridges](http://jump.dev/

| MOI Function |
|:-------:|
| `SingleVariable` |
| `VariableIndex` |
| `ScalarAffineFunction` |

## Dualize a model
Expand Down
6 changes: 2 additions & 4 deletions src/Dualization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ const MOI = MathOptInterface
const MOIU = MathOptInterface.Utilities
const MOIB = MathOptInterface.Bridges

const SVF = MOI.SingleVariable
const VI = MOI.VariableIndex
const CI = MOI.ConstraintIndex
const VVF = MOI.VectorOfVariables
const SAF{T} = MOI.ScalarAffineFunction{T}
const VAF{T} = MOI.VectorAffineFunction{T}
const SQF{T} = MOI.ScalarQuadraticFunction{T}
const VQF{T} = MOI.VectorQuadraticFunction{T}

const VI = MOI.VariableIndex
const CI = MOI.ConstraintIndex

include("structures.jl")
include("utils.jl")
include("dual_sets.jl")
Expand Down
10 changes: 5 additions & 5 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function MOI.supports(
optimizer::DualOptimizer{T},
::MOI.ObjectiveFunction{F},
) where {T,F}
# If the objective function is `MOI.SingleVariable` or `MOI.ScalarAffineFunction`,
# If the objective function is `MOI.VariableIndex` or `MOI.ScalarAffineFunction`,
# a `MOI.ScalarAffineFunction` is set as objective function for the dual problem.
# If it is `MOI.ScalarQuadraticFunction` , a `MOI.ScalarQuadraticFunction` is set as objective function for the dual problem.
G =
Expand All @@ -83,7 +83,7 @@ end

function MOI.supports_constraint(
optimizer::DualOptimizer{T},
F::Type{<:Union{MOI.SingleVariable,MOI.ScalarAffineFunction{T}}},
F::Type{<:Union{MOI.VariableIndex,MOI.ScalarAffineFunction{T}}},
S::Type{<:MOI.AbstractScalarSet},
) where {T}
D = _dual_set_type(S)
Expand Down Expand Up @@ -210,7 +210,7 @@ function MOI.copy_to(dest::DualOptimizer, src::MOI.ModelLike; kwargs...)
setindex!(idx_map, vi, vi)
end

for (F, S) in MOI.get(src, MOI.ListOfConstraints())
for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())
for con in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())
setindex!(idx_map, con, con)
end
Expand Down Expand Up @@ -267,7 +267,7 @@ end
function _get(
::DualOptimizer{T},
::MOI.AbstractConstraintAttribute,
::MOI.ConstraintIndex{MOI.SingleVariable,MOI.EqualTo{T}},
::MOI.ConstraintIndex{MOI.VariableIndex,MOI.EqualTo{T}},
::MOI.ConstraintIndex{Nothing,Nothing},
) where {T}
return zero(T)
Expand Down Expand Up @@ -295,7 +295,7 @@ end
function _get_at_index(
optimizer::DualOptimizer,
attr::MOI.AbstractConstraintAttribute,
ci_primal::MOI.ConstraintIndex{MOI.SingleVariable},
ci_primal::MOI.ConstraintIndex{MOI.VariableIndex},
ci_dual::MOI.ConstraintIndex,
idx,
)
Expand Down
12 changes: 6 additions & 6 deletions src/constrained_variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ function add_constrained_variables(
single_or_vector_variables_types =
MOIU.sorted_variable_sets_by_cost(dual_problem.dual_model, primal_model)
params = Set(variable_parameters)
for (F, S) in single_or_vector_variables_types
if F === MOI.VectorOfVariables
for S in single_or_vector_variables_types
if S <: MOI.AbstractVectorSet
Comment thread
blegat marked this conversation as resolved.
_add_constrained_variables(
dual_problem.primal_dual_map,
primal_model,
S,
params,
)
elseif F === MOI.SingleVariable
elseif S <: MOI.AbstractScalarSet
_add_constrained_variable(
dual_problem.primal_dual_map,
primal_model,
Expand Down Expand Up @@ -59,16 +59,16 @@ function _add_constrained_variable(
) where {S<:MOI.AbstractScalarSet}
cis = MOI.get(
primal_model,
MOI.ListOfConstraintIndices{MOI.SingleVariable,S}(),
MOI.ListOfConstraintIndices{MOI.VariableIndex,S}(),
)
for ci in cis
f = MOI.get(primal_model, MOI.ConstraintFunction(), ci)
if !haskey(m.constrained_var_idx, f.variable) && !(f.variable in params)
if !haskey(m.constrained_var_idx, f) && !(f in params)
set = MOI.get(primal_model, MOI.ConstraintSet(), ci)
if !iszero(MOI.constant(set))
continue
end
m.constrained_var_idx[f.variable] = (ci, 1)
m.constrained_var_idx[f] = (ci, 1)
# Placeholder to indicate this constraint is part of constrained variables,
# it will be replaced later with a dual constraints
m.constrained_var_dual[ci] = CI{Nothing,Nothing}(0)
Expand Down
42 changes: 21 additions & 21 deletions src/dual_equality_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function add_dual_equality_constraints(
primal_dual_map::PrimalDualMap,
dual_names::DualNames,
primal_objective::PrimalObjective{T},
con_types::Vector{Tuple{DataType,DataType}},
con_types::Vector{Tuple{Type,Type}},
variable_parameters::Vector{VI},
) where {T}
sense_change =
Expand Down Expand Up @@ -141,15 +141,15 @@ function _add_constrained_variable_constraint(
primal_model,
zero_map,
ci_map,
ci::MOI.ConstraintIndex{MOI.SingleVariable,<:MOI.EqualTo},
ci::MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.EqualTo},
scalar_affine_terms,
scalar_terms,
sense_change,
::Type{T},
) where {T}
# Nothing to add as the set is `EqualTo`.
func_primal = MOI.get(primal_model, MOI.ConstraintFunction(), ci)
primal_vi = func_primal.variable
primal_vi = func_primal
return zero_map[ci] = MOI.ScalarAffineFunction(
MOIU.operate_terms(-, scalar_affine_terms[primal_vi]),
sense_change * get(scalar_terms, primal_vi, zero(T)),
Expand All @@ -160,14 +160,14 @@ function _add_constrained_variable_constraint(
primal_model,
zero_map,
ci_map,
ci::MOI.ConstraintIndex{MOI.SingleVariable},
ci::MOI.ConstraintIndex{MOI.VariableIndex},
scalar_affine_terms,
scalar_terms,
sense_change,
::Type{T},
) where {T}
func_primal = MOI.get(primal_model, MOI.ConstraintFunction(), ci)
primal_vi = func_primal.variable
primal_vi = func_primal
func_dual = MOI.ScalarAffineFunction(
MOIU.operate_terms(-, scalar_affine_terms[primal_vi]),
sense_change * get(scalar_terms, primal_vi, zero(T)),
Expand All @@ -185,23 +185,23 @@ function add_scalar_affine_terms_from_quad_obj(
primal_objective::PrimalObjective{T},
) where {T}
for term in primal_objective.obj.quadratic_terms
if term.variable_index_1 == term.variable_index_2
dual_vi = primal_var_dual_quad_slack[term.variable_index_1]
if term.variable_1 == term.variable_2
dual_vi = primal_var_dual_quad_slack[term.variable_1]
push_to_scalar_affine_terms!(
scalar_affine_terms[term.variable_index_1],
scalar_affine_terms[term.variable_1],
-MOI.coefficient(term),
dual_vi,
)
else
dual_vi_1 = primal_var_dual_quad_slack[term.variable_index_1]
dual_vi_1 = primal_var_dual_quad_slack[term.variable_1]
push_to_scalar_affine_terms!(
scalar_affine_terms[term.variable_index_2],
scalar_affine_terms[term.variable_2],
-MOI.coefficient(term),
dual_vi_1,
)
dual_vi_2 = primal_var_dual_quad_slack[term.variable_index_2]
dual_vi_2 = primal_var_dual_quad_slack[term.variable_2]
push_to_scalar_affine_terms!(
scalar_affine_terms[term.variable_index_1],
scalar_affine_terms[term.variable_1],
-MOI.coefficient(term),
dual_vi_2,
)
Expand All @@ -216,7 +216,7 @@ function add_scalar_affine_terms_from_quad_params(
) where {T}
for (key, val) in primal_objective.quad_cross_parameters
for term in val
dual_vi = primal_parameter[term.variable_index]
dual_vi = primal_parameter[term.variable]
push_to_scalar_affine_terms!(
scalar_affine_terms[key],
-MOI.coefficient(term),
Expand Down Expand Up @@ -245,10 +245,10 @@ end
function get_scalar_terms(primal_objective::PrimalObjective{T}) where {T}
scalar_terms = Dict{VI,T}()
for term in get_affine_terms(primal_objective)
if haskey(scalar_terms, term.variable_index)
scalar_terms[term.variable_index] += MOI.coefficient(term)
if haskey(scalar_terms, term.variable)
scalar_terms[term.variable] += MOI.coefficient(term)
else
scalar_terms[term.variable_index] = MOI.coefficient(term)
scalar_terms[term.variable] = MOI.coefficient(term)
end
end
return scalar_terms
Expand Down Expand Up @@ -276,7 +276,7 @@ function get_scalar_affine_terms(
primal_model::MOI.ModelLike,
primal_con_dual_var::Dict{CI,Vector{VI}},
variables::Vector{VI},
con_types::Vector{Tuple{DataType,DataType}},
con_types::Vector{Tuple{Type,Type}},
::Type{T},
) where {T}
scalar_affine_terms = Dict{VI,Vector{MOI.ScalarAffineTerm{T}}}(
Expand Down Expand Up @@ -315,7 +315,7 @@ function fill_scalar_affine_terms!(
for term in moi_function.terms
dual_vi = primal_con_dual_var[ci][1] # In this case we only have one vi
push_to_scalar_affine_terms!(
scalar_affine_terms[term.variable_index],
scalar_affine_terms[term.variable],
MOI.coefficient(term),
dual_vi,
)
Expand All @@ -327,7 +327,7 @@ function fill_scalar_affine_terms!(
scalar_affine_terms::Dict{VI,Vector{MOI.ScalarAffineTerm{T}}},
primal_con_dual_var::Dict{CI,Vector{VI}},
primal_model::MOI.ModelLike,
ci::CI{SVF,S},
ci::CI{VI,S},
) where {T,S<:Union{MOI.GreaterThan{T},MOI.LessThan{T},MOI.EqualTo{T}}}
dual_var = get(primal_con_dual_var, ci, nothing)
if dual_var === nothing
Expand All @@ -336,7 +336,7 @@ function fill_scalar_affine_terms!(
moi_function = get_function(primal_model, ci)
dual_vi = dual_var[1] # In this case we only have one vi
push_to_scalar_affine_terms!(
scalar_affine_terms[moi_function.variable],
scalar_affine_terms[moi_function],
one(T),
dual_vi,
)
Expand All @@ -356,7 +356,7 @@ function fill_scalar_affine_terms!(
# term.output_index is the row of the VAF,
# it corresponds to the dual variable associated with this constraint
push_to_scalar_affine_terms!(
scalar_affine_terms[term.scalar_term.variable_index],
scalar_affine_terms[term.scalar_term.variable],
set_dot(term.output_index, set, T) * MOI.coefficient(term),
dual_vi,
)
Expand Down
8 changes: 4 additions & 4 deletions src/dual_model_variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function add_dual_vars_in_dual_cones(
) where {T,F,S}
for ci in MOI.get(primal_model, MOI.ListOfConstraintIndices{F,S}()) # Constraints of type {F, S}
# If `F` not one of these two, we can skip the `in` check.
if (F === MOI.VectorOfVariables || F === MOI.SingleVariable) &&
if (F === MOI.VectorOfVariables || F === MOI.VariableIndex) &&
haskey(primal_dual_map.constrained_var_dual, ci)
continue
end
Expand Down Expand Up @@ -43,7 +43,7 @@ function add_dual_vars_in_dual_cones(
primal_model::MOI.ModelLike,
primal_dual_map::PrimalDualMap{T},
dual_names::DualNames,
con_types::Vector{Tuple{DataType,DataType}},
con_types::Vector{Tuple{Type,Type}},
) where {T}
dual_obj_affine_terms = Dict{VI,T}()
for (F, S) in con_types
Expand Down Expand Up @@ -184,7 +184,7 @@ function add_primal_parameter_vars(
added = Set{VI}()
for vec in values(primal_objective.quad_cross_parameters)
for term in vec
ind = term.variable_index
ind = term.variable
if ind in added
# do nothing
else
Expand Down Expand Up @@ -271,7 +271,7 @@ function add_quadratic_slack_vars(
# are required
added = Set{VI}()
for term in primal_objective.obj.quadratic_terms
for ind in [term.variable_index_1, term.variable_index_2]
for ind in [term.variable_1, term.variable_2]
if ind in added
#do nothing
else
Expand Down
14 changes: 7 additions & 7 deletions src/dualize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function dualize(
ignore_objective::Bool = false,
)
# Creates an empty dual problem
dual_problem = DualProblem{Float64}()
dual_problem = Dualization.DualProblem{Float64}()
return dualize(
primal_model,
dual_problem,
Expand Down Expand Up @@ -43,18 +43,18 @@ function dualize(
ignore_objective::Bool,
) where {T}
# Throws an error if objective function cannot be dualized
supported_objective(primal_model)
Dualization.supported_objective(primal_model)

# Query all constraint types of the model
con_types = MOI.get(primal_model, MOI.ListOfConstraints())
supported_constraints(con_types) # Throws an error if constraint cannot be dualized
con_types = MOI.get(primal_model, MOI.ListOfConstraintTypesPresent())
Dualization.supported_constraints(con_types) # Throws an error if constraint cannot be dualized

# Set the dual model objective sense
set_dual_model_sense(dual_problem.dual_model, primal_model)
Dualization.set_dual_model_sense(dual_problem.dual_model, primal_model)

# Get Primal Objective Coefficients
primal_objective =
get_primal_objective(primal_model, variable_parameters, T)
Dualization.get_primal_objective(primal_model, variable_parameters, T)

add_constrained_variables(dual_problem, primal_model, variable_parameters)

Expand Down Expand Up @@ -204,7 +204,7 @@ function fill_obj_dict_with_variables!(model::JuMP.Model)
end

function fill_obj_dict_with_constraints!(model::JuMP.Model)
con_types = MOI.get(model, JuMP.MOI.ListOfConstraints())
con_types = MOI.get(model, JuMP.MOI.ListOfConstraintTypesPresent())
for (F, S) in con_types
fill_obj_dict_with_constraints!(model, F, S)
end
Expand Down
Loading