Skip to content

Commit

Permalink
Merge pull request #127 from jump-dev/bump_moi_jump
Browse files Browse the repository at this point in the history
Fixes for JuMP 0.22 and MOI 0.10
  • Loading branch information
guilhermebodin authored Jan 7, 2022
2 parents a210f62 + 489cb22 commit 5866bbf
Show file tree
Hide file tree
Showing 33 changed files with 224 additions and 323 deletions.
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 <[email protected]>"]
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
_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

2 comments on commit 5866bbf

@guilhermebodin
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/51908

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.0 -m "<description of version>" 5866bbf250a218b42324b4f9655b23947bdbe925
git push origin v0.4.0

Please sign in to comment.