From acb853098c6a1c54ac7c25a76a7ef00757d9b85a Mon Sep 17 00:00:00 2001 From: Lara Pontes Date: Thu, 12 Aug 2021 02:40:28 -0300 Subject: [PATCH 1/4] add delete and modify methods for constraints --- src/MOIwrapper.jl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/MOIwrapper.jl b/src/MOIwrapper.jl index e351b6bb7..25484e999 100644 --- a/src/MOIwrapper.jl +++ b/src/MOIwrapper.jl @@ -207,6 +207,48 @@ function MOI.add_constraint( return constrid end +############################################################################################ +# Delete and modify constraint +############################################################################################ +function MOI.delete( + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}} +) + constrid = getid(model.constrs[ci]) + orig_form = model.inner.original_formulation + coefmatrix = getcoefmatrix(orig_form) + varids = VarId[] + for (varid, _) in @view coefmatrix[constrid, :] + push!(varids, varid) + end + for varid in varids + coefmatrix[constrid, varid] = 0.0 + end + delete!(orig_form.buffer.constr_buffer.added, constrid) + delete!(orig_form.manager.constrs, constrid) + delete!(model.constrs, ci) + return +end + +function MOI.modify( + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}}, + change::MOI.ScalarConstantChange{Float64} +) + constr = model.constrs[ci] + constr.perendata.rhs = change.new_constant + constr.curdata.rhs = change.new_constant + return +end + +function MOI.modify( + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}}, + change::MOI.ScalarCoefficientChange{Float64} +) + varid = getid(model.vars[change.variable]) + constrid = getid(model.constrs[ci]) + getcoefmatrix(model.inner.original_formulation)[constrid, varid] = change.new_coefficient + return +end + ############################################################################################ # Get variables ############################################################################################ From 875f42f39d5f8837cb5c0d51d7b41224f8065697 Mon Sep 17 00:00:00 2001 From: Lara Pontes Date: Fri, 13 Aug 2021 00:38:15 -0300 Subject: [PATCH 2/4] add delete and modify methods for variables --- src/MOIwrapper.jl | 53 ++++++++++++++++++++++++---- test/MathOptInterface/MOI_wrapper.jl | 16 ++++----- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/MOIwrapper.jl b/src/MOIwrapper.jl index 25484e999..c2d16ac52 100644 --- a/src/MOIwrapper.jl +++ b/src/MOIwrapper.jl @@ -207,12 +207,53 @@ function MOI.add_constraint( return constrid end +############################################################################################ +# Delete and modify variable +############################################################################################ +function MOI.delete(model::Coluna.Optimizer, vi::MOI.VariableIndex) + MOI.modify(model, MoiObjective(), MOI.ScalarCoefficientChange(vi, 0.0)) + for (ci, _) in model.constrs_on_single_var_to_vars + if ci.value == vi.value + MOI.delete(model, ci) + break + end + end + for (ci, _) in model.constrs + MOI.modify(model, ci, MOI.ScalarCoefficientChange(vi, 0.0)) + end + varid = getid(model.vars[vi]) + orig_form = model.inner.original_formulation + delete!(orig_form.manager.vars, varid) + delete!(orig_form.buffer.var_buffer.added, varid) + delete!(model.moi_varids, varid) + delete!(model.vars, vi) + delete!(model.env.varids, vi) + return +end + +function MOI.modify( + model::Coluna.Optimizer, ::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}, + change::MathOptInterface.ScalarCoefficientChange{Float64} +) + var = model.vars[change.variable] + var.perendata.cost = change.new_coefficient + var.curdata.cost = change.new_coefficient + return +end + ############################################################################################ # Delete and modify constraint ############################################################################################ +# issue #583 +# function MOI.delete( +# model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S} +# ) where {F<:MOI.SingleVariable,S} +# return +# end + function MOI.delete( - model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}} -) + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S} +) where {F<:MOI.ScalarAffineFunction{Float64},S} constrid = getid(model.constrs[ci]) orig_form = model.inner.original_formulation coefmatrix = getcoefmatrix(orig_form) @@ -230,9 +271,9 @@ function MOI.delete( end function MOI.modify( - model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}}, + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S}, change::MOI.ScalarConstantChange{Float64} -) +) where {F<:MOI.ScalarAffineFunction{Float64},S} constr = model.constrs[ci] constr.perendata.rhs = change.new_constant constr.curdata.rhs = change.new_constant @@ -240,9 +281,9 @@ function MOI.modify( end function MOI.modify( - model::Coluna.Optimizer, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}}, + model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S}, change::MOI.ScalarCoefficientChange{Float64} -) +) where {F<:MOI.ScalarAffineFunction{Float64},S} varid = getid(model.vars[change.variable]) constrid = getid(model.constrs[ci]) getcoefmatrix(model.inner.original_formulation)[constrid, varid] = change.new_coefficient diff --git a/test/MathOptInterface/MOI_wrapper.jl b/test/MathOptInterface/MOI_wrapper.jl index 3225aac03..770fe2e3d 100644 --- a/test/MathOptInterface/MOI_wrapper.jl +++ b/test/MathOptInterface/MOI_wrapper.jl @@ -113,9 +113,7 @@ end const UNSUPPORTED_TESTS = [ "solve_qcp_edge_cases", # Quadratic constraints not supported - "delete_nonnegative_variables", # variable deletion not supported - "delete_variable", # variable deletion not supported - "delete_variables", # variable deletion not supported + "delete_nonnegative_variables", # `VectorOfVariables`-in-`Nonnegatives` not supported "variablenames", # Coluna retrieves the name of the variable "delete_soc_variables", # soc variables not supported "solve_qp_edge_cases", # Quadratic objective not supported @@ -194,12 +192,10 @@ const CONSTRAINTDUAL_SINGLEVAR = [ "linear14" ] -const MODIFY_DELETE = [ - # BUG - "linear1", # modify - "linear5", # modify - "linear11", # delete - "linear14" # delete +const DELETE_SINGLEVAR_CONSTR = [ + # BUG: issue #583 + "linear5", + "linear14" ] const UNCOVERED_TERMINATION_STATUS = [ @@ -242,7 +238,7 @@ end @testset "Continuous Linear" begin MOIT.contlineartest(BRIDGED, CONFIG, vcat( - CONSTRAINTDUAL_SINGLEVAR, MODIFY_DELETE, UNCOVERED_TERMINATION_STATUS, SET_CONSTRAINTSET, [ + CONSTRAINTDUAL_SINGLEVAR, DELETE_SINGLEVAR_CONSTR, UNCOVERED_TERMINATION_STATUS, SET_CONSTRAINTSET, [ "partial_start", # VariablePrimalStart not supported "linear1", # TODO: support duplicate terms "linear10" # BUG: optimize twice changing sense from max to min fails From 018216753f6b26d5ed4933d542a19b7c17e31946 Mon Sep 17 00:00:00 2001 From: Guillaume Marques Date: Fri, 13 Aug 2021 08:38:03 +0200 Subject: [PATCH 3/4] fix merge commit --- test/MathOptInterface/MOI_wrapper.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/MathOptInterface/MOI_wrapper.jl b/test/MathOptInterface/MOI_wrapper.jl index 639cffa42..14c147ace 100644 --- a/test/MathOptInterface/MOI_wrapper.jl +++ b/test/MathOptInterface/MOI_wrapper.jl @@ -236,7 +236,7 @@ end @testset "Continuous Linear" begin MOIT.contlineartest(BRIDGED, CONFIG, vcat( - CONSTRAINTDUAL_SINGLEVAR, MODIFY_DELETE, UNCOVERED_TERMINATION_STATUS, SET_CONSTRAINTSET, [ + CONSTRAINTDUAL_SINGLEVAR, DELETE_SINGLEVAR_CONSTR, UNCOVERED_TERMINATION_STATUS, SET_CONSTRAINTSET, [ "partial_start" # VariablePrimalStart not supported ] )) From da2a964fbc38d351c54713c6e2949b7b2dc9902f Mon Sep 17 00:00:00 2001 From: Lara Pontes Date: Fri, 13 Aug 2021 13:48:55 -0300 Subject: [PATCH 4/4] add delete! and use proper get and set methods --- src/MOIwrapper.jl | 21 ++++++++------------- src/MathProg/MathProg.jl | 2 +- src/MathProg/varconstr.jl | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/MOIwrapper.jl b/src/MOIwrapper.jl index 1fef24b9b..f694da4b5 100644 --- a/src/MOIwrapper.jl +++ b/src/MOIwrapper.jl @@ -224,9 +224,7 @@ function MOI.delete(model::Coluna.Optimizer, vi::MOI.VariableIndex) MOI.modify(model, ci, MOI.ScalarCoefficientChange(vi, 0.0)) end varid = getid(model.vars[vi]) - orig_form = model.inner.original_formulation - delete!(orig_form.manager.vars, varid) - delete!(orig_form.buffer.var_buffer.added, varid) + delete!(get_original_formulation(model.inner), varid) delete!(model.moi_varids, varid) delete!(model.vars, vi) delete!(model.env.varids, vi) @@ -237,9 +235,9 @@ function MOI.modify( model::Coluna.Optimizer, ::MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}, change::MathOptInterface.ScalarCoefficientChange{Float64} ) - var = model.vars[change.variable] - var.perendata.cost = change.new_coefficient - var.curdata.cost = change.new_coefficient + setperencost!( + get_original_formulation(model.inner), model.vars[change.variable], change.new_coefficient + ) return end @@ -257,7 +255,7 @@ function MOI.delete( model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S} ) where {F<:MOI.ScalarAffineFunction{Float64},S} constrid = getid(model.constrs[ci]) - orig_form = model.inner.original_formulation + orig_form = get_original_formulation(model.inner) coefmatrix = getcoefmatrix(orig_form) varids = VarId[] for (varid, _) in @view coefmatrix[constrid, :] @@ -266,8 +264,7 @@ function MOI.delete( for varid in varids coefmatrix[constrid, varid] = 0.0 end - delete!(orig_form.buffer.constr_buffer.added, constrid) - delete!(orig_form.manager.constrs, constrid) + delete!(orig_form, constrid) delete!(model.constrs, ci) return end @@ -276,9 +273,7 @@ function MOI.modify( model::Coluna.Optimizer, ci::MOI.ConstraintIndex{F,S}, change::MOI.ScalarConstantChange{Float64} ) where {F<:MOI.ScalarAffineFunction{Float64},S} - constr = model.constrs[ci] - constr.perendata.rhs = change.new_constant - constr.curdata.rhs = change.new_constant + setperenrhs!(get_original_formulation(model.inner), model.constrs[ci], change.new_constant) return end @@ -288,7 +283,7 @@ function MOI.modify( ) where {F<:MOI.ScalarAffineFunction{Float64},S} varid = getid(model.vars[change.variable]) constrid = getid(model.constrs[ci]) - getcoefmatrix(model.inner.original_formulation)[constrid, varid] = change.new_coefficient + getcoefmatrix(get_original_formulation(model.inner))[constrid, varid] = change.new_coefficient return end diff --git a/src/MathProg/MathProg.jl b/src/MathProg/MathProg.jl index 9a18589e9..fe17cd8d1 100644 --- a/src/MathProg/MathProg.jl +++ b/src/MathProg/MathProg.jl @@ -8,7 +8,7 @@ import TimerOutputs import ..Coluna # for NestedEnum (types.jl:210) using ..ColunaBase -import Base: haskey, length, iterate, diff +import Base: haskey, length, iterate, diff, delete! using DynamicSparseArrays, Logging, Printf diff --git a/src/MathProg/varconstr.jl b/src/MathProg/varconstr.jl index 83e047d21..8b16eacfe 100644 --- a/src/MathProg/varconstr.jl +++ b/src/MathProg/varconstr.jl @@ -453,6 +453,26 @@ function deactivate!(form::Formulation, f::Function) return end +## delete +""" + delete!(formulation, varconstrid) + delete!(formulation, varconstr) + +Delete a variable or a constraint from a formulation. +""" +function Base.delete!(form::Formulation, varid::VarId) + delete!(form.manager.vars, varid) + delete!(form.buffer.var_buffer.added, varid) + return +end +Base.delete!(form::Formulation, var::Variable) = delete!(form, getid(var)) + +function Base.delete!(form::Formulation, constrid::ConstrId) + delete!(form.buffer.constr_buffer.added, constrid) + delete!(form.manager.constrs, constrid) +end +Base.delete!(form::Formulation, constr::Constraint) = delete!(form, getid(constr)) + ## explicit """ isexplicit(formulation, varconstr)