From 58a9c289108d9b0a80f4913228f1ac3acf4539ef Mon Sep 17 00:00:00 2001 From: rafabench Date: Mon, 2 May 2022 15:44:07 -0300 Subject: [PATCH 1/2] add MOI.modify for multiple changes at once --- src/MOI_wrapper/MOI_wrapper.jl | 34 +++++++++++++++++++++++++ test/MOI_wrapper.jl | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index 6f3840a..1ad9bcf 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -2155,6 +2155,40 @@ function MOI.modify( return end +function MOI.modify( + model::Optimizer, + cis::Vector{MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},S}}, + changes::Vector{MOI.ScalarCoefficientChange{Float64}}, +) where {S} + nels = length(cis) + @assert nels == length(changes) + rows = Vector{Cint}(undef, nels) + cols = Vector{Cint}(undef, nels) + coefs = Vector{Cdouble}(undef, nels) + for i in 1:nels + row = Cint(_info(model, cis[i]).row) + col = column(model, changes[i].variable) + nnz = glp_get_mat_row(model, row, C_NULL, C_NULL) + indices, coefficients = zeros(Cint, nnz), zeros(Cdouble, nnz) + glp_get_mat_row(model, row, offset(indices), offset(coefficients)) + index = something(findfirst(isequal(col), indices), 0) + if index > 0 + coefficients[index] = changes[i].new_coefficient + else + push!(indices, cols[i]) + push!(coefficients, changes[i].new_coefficient) + end + glp_set_mat_row( + model, + row, + length(indices), + offset(indices), + offset(coefficients), + ) + end + return +end + function MOI.set( model::Optimizer, ::MOI.ConstraintFunction, diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index be5a7f1..7fa20d4 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -544,6 +544,51 @@ function test_variable_basis_status() return end +function test_multiple_modifications() + model = GLPK.Optimizer() + + x = MOI.add_variables(model, 3) + + saf = MOI.ScalarAffineFunction( + [ + MOI.ScalarAffineTerm(1.0, x[1]), + MOI.ScalarAffineTerm(1.0, x[2]), + MOI.ScalarAffineTerm(1.0, x[3]), + ], + 0.0, + ) + ci1 = MOI.add_constraint(model, saf, MOI.LessThan(1.0)) + ci2 = MOI.add_constraint(model, saf, MOI.LessThan(2.0)) + + MOI.set( + model, + MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + saf, + ) + + fc1 = MOI.get(model, MOI.ConstraintFunction(), ci1) + @test MOI.coefficient.(fc1.terms) == [1.0, 1.0, 1.0] + fc2 = MOI.get(model, MOI.ConstraintFunction(), ci2) + @test MOI.coefficient.(fc2.terms) == [1.0, 1.0, 1.0] + obj = MOI.get( + model, + MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + ) + @test MOI.coefficient.(obj.terms) == [1.0, 1.0, 1.0] + + changes_cis = [ + MOI.ScalarCoefficientChange(MOI.VariableIndex(1), 4.0) + MOI.ScalarCoefficientChange(MOI.VariableIndex(1), 0.5) + MOI.ScalarCoefficientChange(MOI.VariableIndex(3), 2.0) + ] + MOI.modify(model, [ci1, ci2, ci2], changes_cis) + + fc1 = MOI.get(model, MOI.ConstraintFunction(), ci1) + @test MOI.coefficient.(fc1.terms) == [4.0, 1.0, 1.0] + fc2 = MOI.get(model, MOI.ConstraintFunction(), ci2) + @test MOI.coefficient.(fc2.terms) == [2.0, 1.0, 0.5] +end + end # module TestMOIWrapper.runtests() From d203670e9eaf0bb23702b556edebafbd5e8280fb Mon Sep 17 00:00:00 2001 From: rafabench Date: Mon, 2 May 2022 16:26:02 -0300 Subject: [PATCH 2/2] fix modify and tests --- src/MOI_wrapper/MOI_wrapper.jl | 22 ++++++++++++++-------- test/MOI_wrapper.jl | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/MOI_wrapper/MOI_wrapper.jl b/src/MOI_wrapper/MOI_wrapper.jl index 1ad9bcf..bbc9e49 100644 --- a/src/MOI_wrapper/MOI_wrapper.jl +++ b/src/MOI_wrapper/MOI_wrapper.jl @@ -2166,17 +2166,23 @@ function MOI.modify( cols = Vector{Cint}(undef, nels) coefs = Vector{Cdouble}(undef, nels) for i in 1:nels - row = Cint(_info(model, cis[i]).row) - col = column(model, changes[i].variable) + rows[i] = Cint(_info(model, cis[i]).row) + cols[i] = column(model, changes[i].variable) + coefs[i] = changes[i].new_coefficient + end + for row in unique(rows) nnz = glp_get_mat_row(model, row, C_NULL, C_NULL) indices, coefficients = zeros(Cint, nnz), zeros(Cdouble, nnz) glp_get_mat_row(model, row, offset(indices), offset(coefficients)) - index = something(findfirst(isequal(col), indices), 0) - if index > 0 - coefficients[index] = changes[i].new_coefficient - else - push!(indices, cols[i]) - push!(coefficients, changes[i].new_coefficient) + idxs_changed_in_row = findall(x -> x == row, rows) + for i in idxs_changed_in_row + index = something(findfirst(isequal(cols[i]), indices), 0) + if index > 0 + coefficients[index] = coefs[i] + else + push!(indices, cols[i]) + push!(coefficients, coefs[i]) + end end glp_set_mat_row( model, diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 7fa20d4..3fe5bd0 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -586,7 +586,7 @@ function test_multiple_modifications() fc1 = MOI.get(model, MOI.ConstraintFunction(), ci1) @test MOI.coefficient.(fc1.terms) == [4.0, 1.0, 1.0] fc2 = MOI.get(model, MOI.ConstraintFunction(), ci2) - @test MOI.coefficient.(fc2.terms) == [2.0, 1.0, 0.5] + @test MOI.coefficient.(fc2.terms) == [0.5, 1.0, 2.0] end end # module