Skip to content

Commit

Permalink
Enable modification of objective function coefficients for DualOptimi…
Browse files Browse the repository at this point in the history
…zer (#100)
  • Loading branch information
guilhermebodin authored Nov 28, 2020
1 parent a8676f4 commit 3a8bb08
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Dualization"
uuid = "191a621a-6537-11e9-281d-650236a99e60"
authors = ["guilhermebodin <[email protected]>"]
version = "0.3.3"
version = "0.3.4"

[deps]
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Expand Down
17 changes: 16 additions & 1 deletion src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ end

function MOI.supports_constraint(
optimizer::DualOptimizer{T},
F::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}},
::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}},
S::Type{<:MOI.AbstractVectorSet}) where T
D = _dual_set_type(S)
if D === nothing
Expand All @@ -89,6 +89,21 @@ function MOI.supports_constraint(
return MOI.supports_add_constrained_variables(optimizer.dual_problem.dual_model, D)
end

function MOI.modify(optimizer::DualOptimizer{T},
::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}},
obj_change::MOI.ScalarCoefficientChange{T}) where T
# We must find the constraint corresponding to the variable in the objective
# function and change its coefficient on the constraint.
ci_to_change = optimizer.dual_problem.primal_dual_map.primal_var_dual_con[obj_change.variable]
sense_change = MOI.get(optimizer.dual_problem.dual_model,
MOI.ObjectiveSense()) == MOI.MAX_SENSE ? one(T) : -one(T)
MOI.set(optimizer.dual_problem.dual_model,
MOI.ConstraintSet(),
ci_to_change,
MOI.EqualTo(sense_change * obj_change.new_coefficient))
return
end

# TODO add this when constrained variables are implemented
#function MOI.supports_add_constrained_variables(
# optimizer::DualOptimizer{T}, S::Type{MOI.Reals}) where T
Expand Down
15 changes: 5 additions & 10 deletions src/dual_equality_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ function add_dual_equality_constraints(dual_model::MOI.ModelLike, primal_model::
all_variables, con_types, T)

# get RHS from objective coeficients
scalar_terms = get_scalar_terms(primal_model,
all_variables, primal_objective)
scalar_terms = get_scalar_terms(primal_objective)

# Add terms from objective:
# Terms from quadratic part
add_scalar_affine_terms_from_quad_obj(scalar_affine_terms, primal_model,
add_scalar_affine_terms_from_quad_obj(scalar_affine_terms,
primal_dual_map.primal_var_dual_quad_slack, primal_objective)
# terms from mixing variables and parameters
add_scalar_affine_terms_from_quad_params(scalar_affine_terms, primal_model,
add_scalar_affine_terms_from_quad_params(scalar_affine_terms,
primal_dual_map.primal_parameter, primal_objective)

for primal_vi in restricted_variables
Expand All @@ -44,7 +43,6 @@ end

function add_scalar_affine_terms_from_quad_obj(
scalar_affine_terms::Dict{VI,Vector{MOI.ScalarAffineTerm{T}}},
primal_model::MOI.ModelLike,
primal_var_dual_quad_slack::Dict{VI, VI},
primal_objective::PrimalObjective{T}) where T
for term in primal_objective.obj.quadratic_terms
Expand All @@ -68,7 +66,6 @@ end

function add_scalar_affine_terms_from_quad_params(
scalar_affine_terms::Dict{VI,Vector{MOI.ScalarAffineTerm{T}}},
primal_model::MOI.ModelLike,
primal_parameter::Dict{VI, VI},
primal_objective::PrimalObjective{T}) where T
for (key,val) in primal_objective.quad_cross_parameters
Expand All @@ -86,9 +83,7 @@ function set_dual_constraint_name(dual_model::MOI.ModelLike, primal_model::MOI.M
return
end

function get_scalar_terms(primal_model::MOI.ModelLike,
variables::Vector{VI},
primal_objective::PrimalObjective{T}) where T
function get_scalar_terms(primal_objective::PrimalObjective{T}) where T

scalar_terms = Dict{VI,T}()
for term in get_affine_terms(primal_objective)
Expand Down Expand Up @@ -196,6 +191,6 @@ function set_dot(i::Integer, s::MOI.AbstractVectorSet, T::Type)
vec[i] = one(T)
return MOIU.set_dot(vec, vec, s)
end
function set_dot(i::Integer, s::MOI.AbstractScalarSet, T::Type)
function set_dot(::Integer, ::MOI.AbstractScalarSet, T::Type)
return one(T)
end
59 changes: 59 additions & 0 deletions test/Tests/test_modify.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@testset "modify" begin
model = Model(GLPK_DUAL_FACTORY)
@variable(model, x[1:2] >= 0)
@constraint(model, 2x[1] + x[2] <= 4)
@constraint(model, x[1] + 2x[2] <= 4)
@objective(model, Max, 4x[1] + 3x[2])
optimize!(model)
@test objective_value(model) 28/3
set_objective_coefficient(model, x[1], 5.0)
optimize!(model)
@test objective_value(model) 10.6666666666

model = Model(GLPK_DUAL_FACTORY)
@variable(model, x[1:2] >= 0)
@constraint(model, 2x[1] + x[2] <= 4)
@constraint(model, x[1] + 2x[2] <= 4)
@objective(model, Min, -4x[1] + -3x[2])
optimize!(model)
@test objective_value(model) -28/3
set_objective_coefficient(model, x[1], -5.0)
optimize!(model)
@test objective_value(model) -10.6666666666

model = Model(SCS_DUAL_FACTORY)
@variable(model, x[1:2] >= 0)
@constraint(model, 2x[1] + x[2] <= 4)
@constraint(model, x[1] + 2x[2] <= 4)
@objective(model, Max, 4x[1] + 3x[2])
optimize!(model)
@test objective_value(model) 28/3 atol=1e-3
set_objective_coefficient(model, x[1], 5.0)
optimize!(model)
@test objective_value(model) 10.6666666666 atol=1e-3

model = Model(SCS_DUAL_FACTORY)
@variable(model, x[1:2] >= 0)
@constraint(model, 2x[1] + x[2] <= 4)
@constraint(model, x[1] + 2x[2] <= 4)
@objective(model, Min, -4x[1] + -3x[2])
optimize!(model)
@test objective_value(model) -28/3 atol=1e-3
set_objective_coefficient(model, x[1], -5.0)
optimize!(model)
@test objective_value(model) -10.6666666666 atol=1e-3

model = Model(SCS_DUAL_FACTORY)
@variable(model, x)
@variable(model, y)
@variable(model, z)
@constraint(model, x + 2y + 3z >= 4)
@constraint(model, x + y >= 1)
@objective(model, Min, x^2 + x*y + y^2 + y*z + z^2)
optimize!(model)
@test objective_value(model) 1.8571 atol=1e-3
# Now the objective is @objective(model, Min, x^2 + x*y + y^2 + y*z + z^2 - 5x)
set_objective_coefficient(model, x, -5.0)
optimize!(model)
@test objective_value(model) -9.15 atol=1e-3
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ include("Solvers/scs_test.jl")

include("Tests/test_JuMP_dualize.jl")
include("Tests/test_MOI_wrapper.jl")
include("Tests/test_modify.jl")

0 comments on commit 3a8bb08

Please sign in to comment.