Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a version of method delete that deletes a vector of variables. #2135

Merged
merged 9 commits into from Jan 12, 2020
16 changes: 16 additions & 0 deletions src/constraints.jl
Expand Up @@ -172,6 +172,22 @@ function delete(model::Model, con_ref::ConstraintRef{Model})
MOI.delete(backend(model), index(con_ref))
end

"""
delete(model::Model, con_refs::Vector{ConstraintRef})
henriquebecker91 marked this conversation as resolved.
Show resolved Hide resolved

Delete the constraints associated with `con_refs` from the model `model`.
Solvers may implement methods for deleting multiple constraints that are
more efficient than repeatedly calling the single constraint delete method.
henriquebecker91 marked this conversation as resolved.
Show resolved Hide resolved
"""
function delete(model::Model, con_refs::Vector{<:ConstraintRef{Model}})
# This is just a fallback of the fallback. To be really useful,
# instead of calling JuMP.delete repeatedly it needs to call a
# (currently unimplemented) fallback in MOI like the one for
# batch variable deletion: https://github.com/JuliaOpt/MathOptInterface.jl/blob/78c15baee/src/indextypes.jl#L119
# Then the solvers may reimplement the fallback in MOI level.
delete.(model, con_refs)
henriquebecker91 marked this conversation as resolved.
Show resolved Hide resolved
end

"""
is_valid(model::Model, con_ref::ConstraintRef{Model})

Expand Down
16 changes: 16 additions & 0 deletions src/variables.jl
Expand Up @@ -176,6 +176,22 @@ function delete(model::Model, variable_ref::VariableRef)
MOI.delete(backend(model), variable_ref.index)
end

"""
delete(model::Model, variable_refs::Vector{VariableRef})

Delete the variables associated with `variable_refs` from the model `model`.
Solvers may implement methods for deleting multiple variables that are
more efficient than repeatedly calling the single variable delete method.
"""
function delete(model::Model, variable_refs::Vector{VariableRef})
if any(model !== owner_model(v) for v in variable_refs)
error("A variable reference you are trying to delete does not " *
"belong to the model.")
end
MOI.delete(backend(model), index.(variable_refs))
return
end

"""
is_valid(model::Model, variable_ref::VariableRef)

Expand Down
6 changes: 6 additions & 0 deletions test/JuMPExtension.jl
Expand Up @@ -75,6 +75,9 @@ function JuMP.delete(model::MyModel, vref::MyVariableRef)
delete!(model.variables, vref.idx)
delete!(model.var_to_name, vref.idx)
end
function JuMP.delete(model::MyModel, vrefs::Vector{MyVariableRef})
JuMP.delete.(model, vrefs)
end
function JuMP.is_valid(model::MyModel, vref::MyVariableRef)
return (model === vref.model &&
vref.idx in keys(model.variables))
Expand Down Expand Up @@ -227,6 +230,9 @@ function JuMP.delete(model::MyModel, constraint_ref::MyConstraintRef)
delete!(model.constraints, constraint_ref.index)
delete!(model.con_to_name, constraint_ref.index)
end
function JuMP.delete(model::MyModel, con_refs::Vector{<:MyConstraintRef})
JuMP.delete.(model, con_refs)
end
function JuMP.is_valid(model::MyModel, constraint_ref::MyConstraintRef)
return (model === constraint_ref.model &&
constraint_ref.index in keys(model.constraints))
Expand Down
15 changes: 15 additions & 0 deletions test/constraint.jl
Expand Up @@ -119,6 +119,21 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel},
@test_throws Exception JuMP.delete(second_model, constraint_ref)
end

@testset "batch delete / is_valid constraints" begin
model = ModelType()
@variable(model, x[1:9])
cons = [@constraint(model, sum(x[1:2:9]) <= 3)]
push!(cons, @constraint(model, sum(x[2:2:8]) <= 2))
push!(cons, @constraint(model, sum(x[1:3:9]) <= 1))
@test all(JuMP.is_valid.(model, cons))
JuMP.delete(model, cons[[1, 3]])
@test all((!JuMP.is_valid).(model, cons[[1, 3]]))
@test JuMP.is_valid(model, cons[2])
second_model = ModelType()
@test_throws Exception JuMP.delete(second_model, cons[[1, 3]])
@test_throws Exception JuMP.delete(second_model, [cons[2]])
end

@testset "Two-sided constraints" begin
m = ModelType()
@variable(m, x)
Expand Down
17 changes: 17 additions & 0 deletions test/variable.jl
Expand Up @@ -500,6 +500,19 @@ function test_variables_constrained_on_creation(ModelType)
@test num_constraints(model, typeof(x), MOI.PositiveSemidefiniteConeTriangle) == 1
end

function test_batch_delete_variables(ModelType)
model = ModelType()
@variable(model, x[1:3] >= 1)
@objective(model, Min, sum([1, 2, 3] .* x))
@test all(is_valid.(model, x))
delete(model, x[[1, 3]])
@test all((!is_valid).(model, x[[1, 3]]))
@test is_valid(model, x[2])
second_model = ModelType()
@test_throws Exception JuMP.delete(second_model, x[2])
henriquebecker91 marked this conversation as resolved.
Show resolved Hide resolved
@test_throws Exception JuMP.delete(second_model, x[[1, 3]])
end

function variables_test(ModelType::Type{<:JuMP.AbstractModel},
VariableRefType::Type{<:JuMP.AbstractVariableRef})
@testset "Variable name" begin
Expand Down Expand Up @@ -577,6 +590,10 @@ function variables_test(ModelType::Type{<:JuMP.AbstractModel},
@testset "Variables constrained on creation" begin
test_variables_constrained_on_creation(ModelType)
end

@testset "Batch deletion of variables" begin
test_batch_delete_variables(ModelType)
end
end

@testset "Variables for JuMP.Model" begin
Expand Down