Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/Utilities/matrix_of_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,18 @@ function _add_set(sets, i, func::MOI.AbstractVectorFunction)
return add_set(sets, i, MOI.output_dimension(func))
end

const _MATRIXOFCONSTRAINTS_MODIFY_NOT_ALLOWED_ERROR_MESSAGE = """
MatrixOfConstraints does not allow modifications to be made to the model once
`MOI.Utilities.final_touch` has been called. This is called at the end of
`MOI.copy_to` and in `MOI.Utilities.attach_optimizer` (which is called by
`MOI.optimize!` in a `MOI.Utilities.CachingOptimizer`). In order to be able to
apply modifications to this model, you should add a layer
`MOI.Utilities.CachingOptimizer(MOI.Utilities.Model{Float64}(), model)`
where `model` is the current model. This will automatically empty `model` when
modifications are done after `MOI.Utilities.final_touch` is called and copy the
model again in `MOI.Utilities.attach_optimizer`.
"""

function _add_constraint(
model::MatrixOfConstraints,
i::Int,
Expand Down Expand Up @@ -343,6 +355,13 @@ function MOI.add_constraint(
if i === nothing || F != _affine_function_type(T, S)
throw(MOI.UnsupportedConstraint{F,S}())
end
if model.final_touch
throw(
MOI.AddConstraintNotAllowed{F,S}(
_MATRIXOFCONSTRAINTS_MODIFY_NOT_ALLOWED_ERROR_MESSAGE,
),
)
end
return _add_constraint(model, i, IdentityMap(), func, set)
end

Expand Down Expand Up @@ -434,6 +453,11 @@ end

function final_touch(model::MatrixOfConstraints, index_map)
if model.final_touch
# If `default_copy_to` calls `final_touch`, then `index_map` is not
# `nothing` and `final_touch` should be `false`.
# When `CachingOptimizer` calls this, `index_map` is `nothing`
# and `final_touch` might be `true`.
# So we are always in a case where `index_map` is `nothing`.
@assert index_map === nothing
return
end
Expand Down
16 changes: 16 additions & 0 deletions test/Utilities/matrix_of_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,22 @@ function test_copy()
return test_copy(MOIU.OneBasedIndexing)
end

function test_modif()
model =
matrix_instance(Int, MOIU.Box{Int}, OrdLP{Int}, MOIU.OneBasedIndexing)
x = MOI.add_variable(model)
fx = MOI.SingleVariable(x)
func = 2fx
set = MOI.EqualTo(1)
c = MOI.add_constraint(model, func, set)
MOIU.final_touch(model, nothing)
@test_throws MOI.DeleteNotAllowed(c) MOI.delete(model, c)
err = MOI.AddConstraintNotAllowed{typeof(func),typeof(set)}(
MOIU._MATRIXOFCONSTRAINTS_MODIFY_NOT_ALLOWED_ERROR_MESSAGE,
)
@test_throws err MOI.add_constraint(model, func, set)
end

end

TestMatrixOfConstraints.runtests()