@@ -152,6 +152,127 @@ function sparse_array_representation(
152152 )
153153end
154154
155+ # In the future, we could replace by https://github.com/jump-dev/MathOptInterface.jl/pull/1238
156+ """
157+ VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction
158+
159+ Represents the function `x ⋅ terms + constant`
160+ as an `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`.
161+ Use [`standard_form`](@ref) to convert it to a `MOI.ScalarAffineFunction{T}`.
162+ """
163+ struct VectorScalarAffineFunction{T,VT} <: MOI.AbstractScalarFunction
164+ terms:: VT
165+ constant:: T
166+ end
167+ MOI. constant (func:: VectorScalarAffineFunction ) = func. constant
168+ function JuMP. coefficient (
169+ func:: VectorScalarAffineFunction ,
170+ vi:: MOI.VariableIndex ,
171+ )
172+ return func. terms[vi. value]
173+ end
174+ function Base. convert (
175+ :: Type{MOI.ScalarAffineFunction{T}} ,
176+ func:: VectorScalarAffineFunction ,
177+ ) where {T}
178+ return MOI. ScalarAffineFunction {T} (
179+ # TODO we should do better if the vector is a `SparseVector`, I think
180+ # I have some code working for both vector types in Polyhedra.jl
181+ MOI. ScalarAffineTerm{T}[
182+ MOI. ScalarAffineTerm {T} (func. terms[i], MOI. VariableIndex (i)) for
183+ i in eachindex (func. terms) if ! iszero (func. terms[i])
184+ ],
185+ func. constant,
186+ )
187+ end
188+ function standard_form (func:: VectorScalarAffineFunction{T} ) where {T}
189+ return convert (MOI. ScalarAffineFunction{T}, func)
190+ end
191+
192+ function MOI. Utilities. operate (
193+ :: typeof (- ),
194+ :: Type{T} ,
195+ func:: VectorScalarAffineFunction{T} ,
196+ ) where {T}
197+ return VectorScalarAffineFunction (
198+ LazyArrays. ApplyArray (- , func. terms),
199+ - func. constant,
200+ )
201+ end
202+
203+ """
204+ struct MatrixScalarQuadraticFunction{T, VT, MT} <: MOI.AbstractScalarFunction
205+ affine::VectorScalarAffineFunction{T,VT}
206+ terms::MT
207+ end
208+
209+ Represents the function `x' * terms * x / 2 + affine` as an
210+ `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`.
211+ Use [`standard_form`](@ref) to convert it to a `MOI.ScalarQuadraticFunction{T}`.
212+ """
213+ struct MatrixScalarQuadraticFunction{T,VT,MT} <: MOI.AbstractScalarFunction
214+ affine:: VectorScalarAffineFunction{T,VT}
215+ terms:: MT
216+ end
217+ MOI. constant (func:: MatrixScalarQuadraticFunction ) = MOI. constant (func. affine)
218+ function JuMP. coefficient (
219+ func:: MatrixScalarQuadraticFunction ,
220+ vi:: MOI.VariableIndex ,
221+ )
222+ return JuMP. coefficient (func. affine, vi)
223+ end
224+
225+ """
226+ MatrixVectorAffineFunction{T, VT} <: MOI.AbstractVectorFunction
227+
228+ Represents the function `terms * x + constant`
229+ as an `MOI.AbstractVectorFunction` where `x[i] = MOI.VariableIndex(i)`.
230+ Use [`standard_form`](@ref) to convert it to a `MOI.VectorAffineFunction{T}`.
231+ """
232+ struct MatrixVectorAffineFunction{AT,VT} <: MOI.AbstractVectorFunction
233+ terms:: AT
234+ constants:: VT
235+ end
236+ MOI. constant (func:: MatrixVectorAffineFunction ) = func. constants
237+ function Base. convert (
238+ :: Type{MOI.VectorAffineFunction{T}} ,
239+ func:: MatrixVectorAffineFunction ,
240+ ) where {T}
241+ return MOI. VectorAffineFunction {T} (
242+ MOI. VectorAffineTerm{T}[
243+ # TODO we should do better if the matrix is a `SparseMatrixCSC`
244+ MOI. VectorAffineTerm (
245+ i,
246+ MOI. ScalarAffineTerm {T} (func. terms[i, j], MOI. VariableIndex (j)),
247+ ) for i in 1 : size (func. terms, 1 ) for
248+ j in 1 : size (func. terms, 2 ) if ! iszero (func. terms[i, j])
249+ ],
250+ func. constants,
251+ )
252+ end
253+ function standard_form (func:: MatrixVectorAffineFunction{T} ) where {T}
254+ return convert (MOI. VectorAffineFunction{T}, func)
255+ end
256+
257+ # Only used for testing at the moment so performance is not critical so
258+ # converting to standard form is ok
259+ function MOIU. isapprox_zero (
260+ func:: Union{VectorScalarAffineFunction,MatrixScalarQuadraticFunction} ,
261+ tol,
262+ )
263+ return MOIU. isapprox_zero (standard_form (func), tol)
264+ end
265+
266+ _scalar (:: Type{<:MatrixVectorAffineFunction} ) = VectorScalarAffineFunction
267+ _scalar (:: Type{<:SparseVectorAffineFunction} ) = SparseScalarAffineFunction
268+
269+ function Base. getindex (
270+ it:: MOI.Utilities.ScalarFunctionIterator{F} ,
271+ output_index:: Integer ,
272+ ) where {F<: Union{MatrixVectorAffineFunction,SparseVectorAffineFunction} }
273+ return _scalar (F)(it. f. terms[output_index, :], it. f. constants[output_index])
274+ end
275+
155276function _index_map_to_oneto! (index_map, v:: MOI.VariableIndex )
156277 if ! haskey (index_map, v)
157278 n = length (index_map. var_map)
0 commit comments