Skip to content

Commit

Permalink
Merge pull request #57 from JuliaOpt/update-MOI-JuMP
Browse files Browse the repository at this point in the history
Update for MOI 0.9 and JuMP 0.20
  • Loading branch information
guilhermebodin authored Sep 16, 2019
2 parents 2a43fe2 + 065ddfd commit 57f0d7e
Show file tree
Hide file tree
Showing 26 changed files with 308 additions and 358 deletions.
10 changes: 5 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name = "Dualization"
uuid = "191a621a-6537-11e9-281d-650236a99e60"
authors = ["guilhermebodin <[email protected]>"]
version = "0.1.0"
version = "0.2.0"

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

[compat]
MathOptInterface = "~0.8.4"
JuMP = "~0.20.0"
MathOptInterface = "~0.9.0"
julia = "1"
JuMP = "~0.19.0"

[extras]
COSMO = "1e616198-aa4e-51ec-90a2-23f7fbd31d8d"
CSDP = "0a46da34-8e4b-519e-b418-48813639ff34"
ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199"
GLPK = "60bf3e95-4087-53dc-ae20-288a0d20c6a6"
SCS = "c946c3f1-0d1f-5ce8-9dea-7daa1f7e2d13"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "GLPK", "ECOS", "CSDP", "COSMO"]
test = ["Test", "GLPK", "ECOS", "CSDP", "SCS"]
6 changes: 4 additions & 2 deletions src/Dualization.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module Dualization

using JuMP
using MathOptInterface
using JuMP, MathOptInterface
const MOI = MathOptInterface
const MOIU = MathOptInterface.Utilities
const MOIB = MathOptInterface.Bridges

const SVF = MOI.SingleVariable
const VVF = MOI.VectorOfVariables
Expand All @@ -13,6 +13,8 @@ const VAF{T} = MOI.VectorAffineFunction{T}
const VI = MOI.VariableIndex
const CI = MOI.ConstraintIndex

import MathOptInterface: dual_set

include("structures.jl")
include("utils.jl")
include("dual_sets.jl")
Expand Down
19 changes: 7 additions & 12 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ function DualOptimizer(dual_optimizer::OT) where {OT <: MOI.ModelLike}
end

function DualOptimizer{T}(dual_optimizer::OT) where {T, OT <: MOI.ModelLike}
dual_problem = DualProblem{T}(MOIU.CachingOptimizer(DualizableModel{T}(), dual_optimizer))
dual_problem = DualProblem{T}(MOIB.full_bridge_optimizer(MOIU.CachingOptimizer(DualizableModel{T}(), dual_optimizer), T))
# discover the type of MOIU.CachingOptimizer(DualizableModel{T}(), dual_optimizer)
Caching_OptimizerType = typeof(dual_problem.dual_model)
return DualOptimizer{T, Caching_OptimizerType}(dual_problem)
OptimizerType = typeof(dual_problem.dual_model)
return DualOptimizer{T, OptimizerType}(dual_problem)
end

function DualOptimizer()
Expand Down Expand Up @@ -195,16 +195,11 @@ function dual_status(term::MOI.TerminationStatusCode)
return term
end

# To be added in MOI 0.9.0
# function MOI.get(optimizer::DualOptimizer, ::MOI.ObjectiveValue)
# return MOI.get(optimizer.dual_optimizer, MOI.DualObjectiveValue())
# end

# function MOI.get(optimizer::DualOptimizer, ::MOI.DualObjectiveValue)
# return MOI.get(optimizer.dual_optimizer, MOI.ObjectiveValue())
# end

function MOI.get(optimizer::DualOptimizer, ::MOI.ObjectiveValue)
return MOI.get(optimizer.dual_problem.dual_model, MOI.DualObjectiveValue())
end

function MOI.get(optimizer::DualOptimizer, ::MOI.DualObjectiveValue)
return MOI.get(optimizer.dual_problem.dual_model, MOI.ObjectiveValue())
end

Expand Down
4 changes: 2 additions & 2 deletions src/add_dual_cone_constraint.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function add_dual_cone_constraint(dual_model::MOI.ModelLike, primal_model::MOI.ModelLike, vi::Vector{VI},
ci::CI{F, S}) where {F <: MOI.AbstractScalarFunction, S <: MOI.AbstractScalarSet}
# In this case vi should have only one entry
return MOI.add_constraint(dual_model, SVF(vi[1]), dual_set(get_set(primal_model, ci)))
return MOI.add_constraint(dual_model, SVF(vi[1]), MOI.dual_set(get_set(primal_model, ci)))
end

function add_dual_cone_constraint(dual_model::MOI.ModelLike, primal_model::MOI.ModelLike, vi::Vector{VI},
Expand All @@ -11,7 +11,7 @@ end

function add_dual_cone_constraint(dual_model::MOI.ModelLike, primal_model::MOI.ModelLike, vis::Vector{VI},
ci::CI{F, S}) where {F <: MOI.AbstractVectorFunction, S <: MOI.AbstractVectorSet}
return MOI.add_constraint(dual_model, VVF(vis), dual_set(get_set(primal_model, ci)))
return MOI.add_constraint(dual_model, VVF(vis), MOI.dual_set(get_set(primal_model, ci)))
end

function add_dual_cone_constraint(dual_model::MOI.ModelLike, primal_model::MOI.ModelLike, vis::Vector{VI},
Expand Down
1 change: 0 additions & 1 deletion src/dual_equality_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ function fill_scalar_affine_terms!(scalar_affine_terms::Vector{MOI.ScalarAffineT
return
end

# Change to spzeros once https://github.com/JuliaOpt/MathOptInterface.jl/pull/805 is merged
function set_dot(i::Int, s::MOI.AbstractVectorSet, T::Type)
vec = zeros(T, MOI.dimension(s))
vec[i] = one(T)
Expand Down
51 changes: 3 additions & 48 deletions src/dual_sets.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
"""
dual_set(s::MOI.AbstractSet) -> MOI.AbstractSet
export dual_set

Returns the dual set of `s`.
"""
function dual_set end

# This should be putted in MOIU and used for Dualization later
# Additional dual_set
function dual_set(::MOI.GreaterThan{T}) where T
return MOI.GreaterThan(zero(T))
end
Expand All @@ -16,44 +11,4 @@ end

function dual_set(::MOI.EqualTo{T}) where T
return # Maybe return Reals in the future
end

function dual_set(s::MOI.Nonpositives)
return copy(s) # The set is self-dual
end

function dual_set(s::MOI.Nonnegatives)
return copy(s) # The set is self-dual
end

function dual_set(::MOI.Zeros)
return # Maybe return Reals in the future
end

function dual_set(s::MOI.SecondOrderCone)
return copy(s) # The set is self-dual
end

function dual_set(s::MOI.RotatedSecondOrderCone)
return copy(s) # The set is self-dual
end

function dual_set(s::MOI.PositiveSemidefiniteConeTriangle)
return copy(s) # The set is self-dual
end

function dual_set(::MOI.ExponentialCone)
return MOI.DualExponentialCone()
end

function dual_set(::MOI.DualExponentialCone)
return MOI.ExponentialCone()
end

function dual_set(s::MOI.PowerCone)
return MOI.DualPowerCone(s.exponent)
end

function dual_set(s::MOI.DualPowerCone)
return MOI.PowerCone(s.exponent)
end
end
2 changes: 1 addition & 1 deletion src/objective_coefficients.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ function get_dual_objective(dual_model::MOI.ModelLike, dual_obj_affine_terms::Di
saf_dual_objective = MOI.ScalarAffineFunction(
MOI.ScalarAffineTerm.(term_vec,
vi_vec),
MOI._constant(get_saf(primal_objective)))
MOI.constant(get_saf(primal_objective)))
return DualObjective{T}(saf_dual_objective)
end
6 changes: 6 additions & 0 deletions src/supported.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ supported_constraint(::Type{VAF{T}}, ::Type{MOI.PowerCone{T}}) where T = true
# DualPowerCone
supported_constraint(::Type{VVF}, ::Type{<:MOI.DualPowerCone}) = true
supported_constraint(::Type{VAF{T}}, ::Type{MOI.DualPowerCone{T}}) where T = true
# NormOneCone
supported_constraint(::Type{VVF}, ::Type{MOI.NormOneCone}) = true
supported_constraint(::Type{<:VAF}, ::Type{MOI.NormOneCone}) = true
# NormInfinityCone
supported_constraint(::Type{VVF}, ::Type{MOI.NormInfinityCone}) = true
supported_constraint(::Type{<:VAF}, ::Type{MOI.NormInfinityCone}) = true

"""
supported_objective(primal_model::MOI.ModelLike)
Expand Down
10 changes: 5 additions & 5 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@ end
function get_scalar_term(model::MOI.ModelLike,
ci::CI{SVF, S}) where {S <: MOI.AbstractScalarSet}

return [- MOIU.getconstant(get_set(model, ci))]
return [- MOI.constant(get_set(model, ci))]
end

function get_scalar_term(model::MOI.ModelLike,
ci::CI{F, S}) where {F <: MOI.AbstractScalarFunction,
S <: MOI.AbstractScalarSet}

return MOIU.constant(get_function(model, ci)) .- MOIU.getconstant(get_set(model, ci))
return [MOI.constant(get_function(model, ci)) - MOI.constant(get_set(model, ci))]
end

# This is used to fill the dual objective dictionary
function get_scalar_term(model::MOI.ModelLike, i::Int,
ci::CI{F, S}) where {F <: MOI.AbstractVectorFunction,
S <: MOI.AbstractVectorSet}
return MOIU.constant(get_function(model, ci))[i]
return MOI.constant(get_function(model, ci))[i]
end

# This is used to fill the dual objective dictionary
function get_scalar_term(model::MOI.ModelLike, i::Int,
ci::CI{SVF, S}) where {S <: MOI.AbstractScalarSet}

return -MOIU.getconstant(get_set(model, ci))
return - MOI.constant(get_set(model, ci))
end

# This is used to fill the dual objective dictionary
Expand All @@ -44,5 +44,5 @@ function get_scalar_term(model::MOI.ModelLike, i::Int,
S <: MOI.AbstractScalarSet}

# In this case there i only one constant in the function and one in the set
return MOIU.constant(get_function(model, ci))[1] - MOIU.getconstant(get_set(model, ci))
return MOI.constant(get_function(model, ci))[1] - MOI.constant(get_set(model, ci))
end
5 changes: 0 additions & 5 deletions test/Problems/Linear/linear_problems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ function lp1_test()
min -4x_2 - 1
s.t.
x_1 + 2x_2 <= 3
x_1 >= 1
x_1 >= 3
=#
model = TestModel{Float64}()
Expand All @@ -15,10 +14,6 @@ function lp1_test()
MOI.ScalarAffineTerm.([1.0, 2.0], X), 0.0),
MOI.LessThan(3.0))

MOI.add_constraint(model,
MOI.SingleVariable(X[1]),
MOI.GreaterThan(1.0))

MOI.add_constraint(model,
MOI.SingleVariable(X[1]),
MOI.GreaterThan(3.0))
Expand Down
18 changes: 0 additions & 18 deletions test/Solvers/cosmo_test.jl

This file was deleted.

4 changes: 2 additions & 2 deletions test/Solvers/csdp_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const CSDPOPT = with_optimizer(CSDP.Optimizer, printlevel = 0)

@testset "CSDP SDP triangle Problems" begin
list_of_sdp_triang_problems = [
sdpt1_test,
sdpt2_test,
# sdpt1_test, # CSDP is returning SLOW_PROGRESS
# sdpt2_test, # CSDP is returning SLOW_PROGRESS
sdpt3_test,
sdpt4_test
]
Expand Down
19 changes: 19 additions & 0 deletions test/Solvers/scs_test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using SCS
const SCSOPT = with_optimizer(SCS.Optimizer, verbose = false)

#TODO
# @testset "SCS Exponential Cone Problems" begin
# list_of_exp_problems = [
# exp1_test,
# exp2_test
# ]
# test_strong_duality(list_of_exp_problems, SCSOPT)
# end

@testset "SCS Power Cone Problems" begin
list_of_pow_problems = [
pow1_test,
pow2_test
]
test_strong_duality(list_of_pow_problems, SCSOPT; atol = 1e-3, rtol = 1e-3)
end
10 changes: 5 additions & 5 deletions test/Tests/test_JuMP_dualize.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using GLPK, COSMO, CSDP
using GLPK, SCS, CSDP

# For testing bug found on issue # 52
function solve_vaf_sdp(factory::JuMP.OptimizerFactory)
Expand All @@ -12,7 +12,7 @@ end

@testset "JuMP dualize" begin
@testset "direct_mode" begin
JuMP_model = JuMP.direct_model(GLPK.Optimizer())
JuMP_model = JuMP.direct_model(MOIU.MockOptimizer(MOIU.Model{Float64}()))
err = ErrorException("Dualization does not support solvers in DIRECT mode")
@test_throws ErrorException dualize(JuMP_model)
end
Expand All @@ -27,11 +27,11 @@ end
@test MOI.get(backend(dual_JuMP_model), MOI.SolverName()) == "GLPK"
end
@testset "set_dot on different sets" begin
primal_cosmo = solve_vaf_sdp(with_optimizer(COSMO.Optimizer, verbose = false))
dual_cosmo = solve_vaf_sdp(with_optimizer(DualOptimizer, COSMO.Optimizer(verbose = false)))
primal_scs = solve_vaf_sdp(with_optimizer(SCS.Optimizer, verbose = 0))
dual_scs = solve_vaf_sdp(with_optimizer(DualOptimizer, SCS.Optimizer(verbose = 0)))
primal_csdp = solve_vaf_sdp(with_optimizer(CSDP.Optimizer, printlevel = 0))
dual_csdp = solve_vaf_sdp(with_optimizer(DualOptimizer, CSDP.Optimizer(printlevel = 0)))
@test isapprox(primal_cosmo, dual_cosmo; atol = 1e-3)
@test isapprox(primal_scs, dual_scs; atol = 1e-3)
@test isapprox(primal_csdp, dual_csdp; atol = 1e-6)
end
end
Loading

2 comments on commit 57f0d7e

@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/3652

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 Julia TagBot is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.0 -m "<description of version>" 57f0d7e838eb776ae616c5ec61a60af5b113a99a
git push origin v0.2.0

Please sign in to comment.