`MultirowChange` overwrites other constraints
import Gurobi
import MathOptInterface
MOI = MathOptInterface
m = Gurobi.Optimizer()
x = MOI.add_variable(m)
# Create two linear constraints, wrapped in a single VectorAffineFunction constraint
n = 2
c1 = MOI.add_constraint(m,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0),
MOI.EqualTo(0.0)
)
# Add another linear constraint
c2 = MOI.add_constraint(m,
MOI.VectorAffineFunction(
[MOI.VectorAffineTerm(i, MOI.ScalarAffineTerm(1.0, x)) for i in 1:n],
zeros(n)
), MOI.Zeros(n)
)
# Now create another variable
y = MOI.add_variable(m)
# Multi-row change
# That Multirow should raise an error, because the output dimension of c1 is 2
MOI.modify(m, c2, MOI.MultirowChange(y, [(1, 1.1), (2, 2.2), (3, 3.3)]))
# The above call did not raise an error, and modified c1
MOI.get(m, MOI.ConstraintFunction(), c1)
outputs
MathOptInterface.ScalarAffineFunction{Float64}(MathOptInterface.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(2.0, VariableIndex(1)), ScalarAffineTerm{Float64}(1.1, VariableIndex(2))], 0.0)
It appears that MOI.modify with a MultirowChange ends up calling LQOI.change_matrix_coefficient!, which simply re-writes matrix coefficients without any checks.
In particular:
- Other constraints can be over-written (cf example above)
- Instead of changing coeff of variable
jof thei-th output dimension of the vector-valued constraint, it changes coeff(i, j)of the whole problem's constraint matrix.
I don't think multirow change has been utilised, so there are probably lots of bugs like this.
Note that the Gurobi wrapper is being re-written (https://github.com/JuliaOpt/Gurobi.jl/pull/216), and it doesn't implement MultirowChange because it doesn't support VectorAffineFunctions.
The most helpful thing would be to add lots of tests to moi hitting various edge cases.
Because Gurobi does not support VectorAffineFunctions, MultirowChanges will be transformed into ScalarCoefficientChange here:
https://github.com/JuliaOpt/MathOptInterface.jl/blob/ef83d2381b2e26a3e6466b8bc34b6687c7c20c61/src/Bridges/Constraint/scalarize.jl#L89-L96