@@ -859,93 +859,114 @@ end
859859function modify_function (f:: VQF , change:: MOI.VectorConstantChange )
860860 return VQF (f. affine_terms, f. quadratic_terms, change. new_constant)
861861end
862+
862863function _modifycoefficient (
863- terms:: Vector{<: MOI.ScalarAffineTerm} ,
864- variable:: VI ,
865- new_coefficient,
866- )
864+ terms:: Vector{MOI.ScalarAffineTerm{T} } ,
865+ variable:: MOI.VariableIndex ,
866+ new_coefficient:: T ,
867+ ) where {T}
867868 terms = copy (terms)
868869 i = something (findfirst (t -> t. variable_index == variable, terms), 0 )
869- if iszero (i)
870- # The variable was not already in the function
870+ if iszero (i) # The variable was not already in the function
871871 if ! iszero (new_coefficient)
872872 push! (terms, MOI. ScalarAffineTerm (new_coefficient, variable))
873873 end
874- else
875- # The variable was already in the function
874+ else # The variable was already in the function
876875 if iszero (new_coefficient)
877876 deleteat! (terms, i)
878877 else
879878 terms[i] = MOI. ScalarAffineTerm (new_coefficient, variable)
880879 end
880+ # To account for duplicates, we need to delete any other instances of
881+ # `variable` in `terms`.
882+ for j = length (terms): - 1 : (i + 1 )
883+ if terms[j]. variable_index == variable
884+ deleteat! (terms, j)
885+ end
886+ end
881887 end
882888 return terms
883889end
884- function modify_function (f:: SAF , change:: MOI.ScalarCoefficientChange )
885- lin = _modifycoefficient (f. terms, change. variable, change. new_coefficient)
886- return SAF (lin, f. constant)
890+
891+ function modify_function (
892+ f:: MOI.ScalarAffineFunction{T} ,
893+ change:: MOI.ScalarCoefficientChange{T} ,
894+ ) where {T}
895+ terms = _modifycoefficient (f. terms, change. variable, change. new_coefficient)
896+ return MOI. ScalarAffineFunction (terms, f. constant)
887897end
888- function modify_function (f:: SQF , change:: MOI.ScalarCoefficientChange )
889- lin = _modifycoefficient (
898+
899+ function modify_function (
900+ f:: MOI.ScalarQuadraticFunction{T} ,
901+ change:: MOI.ScalarCoefficientChange{T} ,
902+ ) where {T}
903+ terms = _modifycoefficient (
890904 f. affine_terms,
891905 change. variable,
892906 change. new_coefficient,
893907 )
894- return SQF (lin , f. quadratic_terms, f. constant)
908+ return MOI . ScalarQuadraticFunction (terms , f. quadratic_terms, f. constant)
895909end
910+
896911function _modifycoefficients (
897- n,
898- terms:: Vector{<:MOI.VectorAffineTerm} ,
899- variable:: VI ,
900- new_coefficients,
901- )
912+ terms:: Vector{MOI.VectorAffineTerm{T}} ,
913+ variable:: MOI.VariableIndex ,
914+ new_coefficients:: Vector{Tuple{Int64,T}} ,
915+ ) where {T}
902916 terms = copy (terms)
903- # Maps between rows in the `MOI.VectorAffineTerm`s and indices in new_coefficients
904- rowmap = Dict (c[1 ] => i for (i, c) in enumerate (new_coefficients))
905- del = Int[]
906- for i in 1 : length (terms)
907- if terms[i]. scalar_term. variable_index == variable
908- row = terms[i]. output_index
909- j = Base. get (rowmap, row, 0 )
910- if ! iszero (j) # If it is zero, it means that the row should not be changed
911- if iszero (new_coefficients[j][2 ])
912- push! (del, i)
913- else
914- terms[i] = MOI. VectorAffineTerm (
915- row,
916- MOI. ScalarAffineTerm (new_coefficients[j][2 ], variable),
917- )
918- end
919- rowmap[row] = 0 # We only change the first term of a row
920- end
917+ coef_dict = Dict (k => v for (k, v) in new_coefficients)
918+ elements_to_delete = Int[]
919+ for (i, term) in enumerate (terms)
920+ if term. scalar_term. variable_index != variable
921+ continue
921922 end
922- end
923- deleteat! (terms, del)
924- for (row, j) in rowmap
925- if ! iszero (j)
926- push! (
927- terms,
928- MOI. VectorAffineTerm (
929- row,
930- MOI. ScalarAffineTerm (new_coefficients[j][2 ], variable),
931- ),
923+ new_coef = Base. get (coef_dict, term. output_index, nothing )
924+ if new_coef === nothing
925+ continue
926+ elseif iszero (new_coef)
927+ push! (elements_to_delete, i)
928+ else
929+ terms[i] = MOI. VectorAffineTerm (
930+ term. output_index,
931+ MOI. ScalarAffineTerm (new_coef, variable),
932932 )
933+ # Set the coefficient to 0.0 so we don't add duplicates.
934+ coef_dict[term. output_index] = zero (T)
933935 end
934936 end
937+ deleteat! (terms, elements_to_delete)
938+ # Add elements that were not previously in `terms`.
939+ for (k, v) in coef_dict
940+ if iszero (v)
941+ continue
942+ end
943+ push! (terms, MOI. VectorAffineTerm (k, MOI. ScalarAffineTerm (v, variable)))
944+ end
935945 return terms
936946end
937- function modify_function (f:: VAF , change:: MOI.MultirowChange )
938- dim = MOI. output_dimension (f)
939- coefficients = change. new_coefficients
940- lin = _modifycoefficients (dim, f. terms, change. variable, coefficients)
941- return VAF (lin, f. constants)
942- end
943- function modify_function (f:: VQF , change:: MOI.MultirowChange )
944- dim = MOI. output_dimension (f)
945- coefficients = change. new_coefficients
946- lin =
947- _modifycoefficients (dim, f. affine_terms, change. variable, coefficients)
948- return VQF (lin, f. quadratic_terms, f. constants)
947+
948+ function modify_function (
949+ f:: MOI.VectorAffineFunction{T} ,
950+ change:: MOI.MultirowChange{T} ,
951+ ) where {T}
952+ terms = _modifycoefficients (
953+ f. terms,
954+ change. variable,
955+ change. new_coefficients,
956+ )
957+ return MOI. VectorAffineFunction (terms, f. constants)
958+ end
959+
960+ function modify_function (
961+ f:: MOI.VectorQuadraticFunction{T} ,
962+ change:: MOI.MultirowChange{T} ,
963+ ) where {T}
964+ terms = _modifycoefficients (
965+ f. affine_terms,
966+ change. variable,
967+ change. new_coefficients,
968+ )
969+ return MOI. VectorQuadraticFunction (terms, f. quadratic_terms, f. constants)
949970end
950971
951972# Arithmetic
0 commit comments