From 351c367fbe974d4b635ef845ad595a1e54033cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 5 Apr 2023 18:11:01 +0200 Subject: [PATCH 1/9] Add back qp_test --- test/utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/utils.jl b/test/utils.jl index 8a4fc77c..6324648a 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -349,6 +349,7 @@ function qp_test(solver; kws...) true, false, ] + qp_test(solver, lt, set_zero, canonicalize; kws...) end end end From 45e5ff80fc797080233d3a84edc5f8ec200665d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 5 Apr 2023 18:23:03 +0200 Subject: [PATCH 2/9] Fix --- test/utils.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/utils.jl b/test/utils.jl index 6324648a..8864dd15 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -183,8 +183,16 @@ function qp_test( n, dobjb.index_map, ) - @_test(spb.quadratic_terms, dQb) - @_test(spb.affine_terms, dqb) + if spb isa DiffOpt.SparseScalarAffineFunction + @test all(iszero, Q) + if isnothing(dQb) + dQb = Q + end + @_test(spb.terms, dqb) + else + @_test(spb.quadratic_terms, dQb) + @_test(spb.affine_terms, dqb) + end # FIXME should multiply by -1 if lt is false funcs = MOI.get.(model, DiffOpt.ReverseConstraintFunction(), cle) From 563e09569f73882b06cf314540f4976902c40530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 6 Apr 2023 13:15:56 +0200 Subject: [PATCH 3/9] Fixes --- src/bridges.jl | 7 +++++++ src/utils.jl | 13 +++++++++++++ test/utils.jl | 6 +++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/bridges.jl b/src/bridges.jl index 517cdfc1..d4121f22 100644 --- a/src/bridges.jl +++ b/src/bridges.jl @@ -17,6 +17,13 @@ function MOI.set( ) end +function MOI.get( + model::MOI.ModelLike, + attr::ReverseConstraintFunction, + bridge::MOI.Bridges.Constraint.VectorizeBridge, +) + MOI.Utilities.eachscalar(MOI.get(model, attr, bridge.vector_constraint))[1] +end function MOI.get( model::MOI.ModelLike, attr::DiffOpt.ReverseConstraintFunction, diff --git a/src/utils.jl b/src/utils.jl index a54c203b..ab1cb1d9 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -152,6 +152,19 @@ function sparse_array_representation( ) end +_scalar(::Type{<:MatrixVectorAffineFunction}) = VectorScalarAffineFunction +_scalar(::Type{<:SparseVectorAffineFunction}) = SparseScalarAffineFunction + +function Base.getindex( + it::MOI.Utilities.ScalarFunctionIterator{F}, + output_index::Integer, +) where {F<:Union{MatrixVectorAffineFunction,SparseVectorAffineFunction}} + return _scalar(F)( + it.f.terms[output_index, :], + it.f.constants[output_index], + ) +end + function _index_map_to_oneto!(index_map, v::MOI.VariableIndex) if !haskey(index_map, v) n = length(index_map.var_map) diff --git a/test/utils.jl b/test/utils.jl index 8864dd15..9f957405 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -256,7 +256,11 @@ function qp_test( end @_test(-A * ∇zb, dνb) - dobjf = v' * (dQf / 2.0) * v + dqf' * v + if all(iszero, dQf) + dobjf = dqf' * v + else + dobjf = v' * (dQf / 2.0) * v + dqf' * v + end dlef = dGf * v .- dhf deqf = dAf * v .- dbf From 92f522ca4d92e06fb837881baeda8d148894d5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 6 Apr 2023 22:40:47 +0200 Subject: [PATCH 4/9] Fix --- src/ConicProgram/ConicProgram.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ConicProgram/ConicProgram.jl b/src/ConicProgram/ConicProgram.jl index 918c6ff9..d04d25c9 100644 --- a/src/ConicProgram/ConicProgram.jl +++ b/src/ConicProgram/ConicProgram.jl @@ -398,9 +398,12 @@ function DiffOpt._get_db( i = MOI.Utilities.rows(model.model.constraints, ci) # vector # i = ci.value n = length(model.x) # columns in A + # Since `b` in https://arxiv.org/pdf/1904.09043.pdf is the constant in the right-hand side and + # `b` in MOI is the constant on the left-hand side, we have the opposite sign here # db = - dQ[n+1:n+m, end] + dQ[end, n+1:n+m]' g = model.back_grad_cache.g πz = model.back_grad_cache.πz + # `g[end] * πz[n .+ i] - πz[end] * g[n .+ i]` return DiffOpt.lazy_combination(-, πz, g, length(g), n .+ i) end @@ -415,7 +418,8 @@ function DiffOpt._get_dA( # dA = - dQ[1:n, n+1:n+m]' + dQ[n+1:n+m, 1:n] g = model.back_grad_cache.g πz = model.back_grad_cache.πz - return DiffOpt.lazy_combination(-, g, πz, i, n .+ (1:n)) + #return DiffOpt.lazy_combination(-, g, πz, n .+ i, 1:n) + return g[n .+ i] * πz[1:n]' - πz[n .+ i] * g[1:n]' end function MOI.get( From 2c951225b4c963c9ec6e38a53f52f0bacf09461e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Sun, 9 Apr 2023 08:58:09 +0200 Subject: [PATCH 5/9] move structs to utils --- src/jump_moi_overloads.jl | 120 -------------------------------------- src/utils.jl | 86 +++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 120 deletions(-) diff --git a/src/jump_moi_overloads.jl b/src/jump_moi_overloads.jl index e5b0918f..9459f840 100644 --- a/src/jump_moi_overloads.jl +++ b/src/jump_moi_overloads.jl @@ -131,82 +131,6 @@ function Base.isapprox( return isapprox(standard_form(func1), standard_form(func2); kws...) end -# In the future, we could replace by https://github.com/jump-dev/MathOptInterface.jl/pull/1238 -""" - VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction - -Represents the function `x ⋅ terms + constant` -as an `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. -Use [`standard_form`](@ref) to convert it to a `MOI.ScalarAffineFunction{T}`. -""" -struct VectorScalarAffineFunction{T,VT} <: MOI.AbstractScalarFunction - terms::VT - constant::T -end - -MOI.constant(func::VectorScalarAffineFunction) = func.constant - -function JuMP.coefficient( - func::VectorScalarAffineFunction, - vi::MOI.VariableIndex, -) - return func.terms[vi.value] -end - -function Base.convert( - ::Type{MOI.ScalarAffineFunction{T}}, - func::VectorScalarAffineFunction, -) where {T} - return MOI.ScalarAffineFunction{T}( - # TODO we should do better if the vector is a `SparseVector`, I think - # I have some code working for both vector types in Polyhedra.jl - MOI.ScalarAffineTerm{T}[ - MOI.ScalarAffineTerm{T}(func.terms[i], MOI.VariableIndex(i)) for - i in eachindex(func.terms) if !iszero(func.terms[i]) - ], - func.constant, - ) -end - -function standard_form(func::VectorScalarAffineFunction{T}) where {T} - return convert(MOI.ScalarAffineFunction{T}, func) -end - -function MOI.Utilities.operate( - ::typeof(-), - ::Type{T}, - func::VectorScalarAffineFunction{T}, -) where {T} - return VectorScalarAffineFunction( - LazyArrays.ApplyArray(-, func.terms), - -func.constant, - ) -end - -""" - struct MatrixScalarQuadraticFunction{T, VT, MT} <: MOI.AbstractScalarFunction - affine::VectorScalarAffineFunction{T,VT} - terms::MT - end - -Represents the function `x' * terms * x / 2 + affine` as an -`MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. -Use [`standard_form`](@ref) to convert it to a `MOI.ScalarQuadraticFunction{T}`. -""" -struct MatrixScalarQuadraticFunction{T,VT,MT} <: MOI.AbstractScalarFunction - affine::VectorScalarAffineFunction{T,VT} - terms::MT -end - -MOI.constant(func::MatrixScalarQuadraticFunction) = MOI.constant(func.affine) - -function JuMP.coefficient( - func::MatrixScalarQuadraticFunction, - vi::MOI.VariableIndex, -) - return JuMP.coefficient(func.affine, vi) -end - function quad_sym_half( func::MatrixScalarQuadraticFunction, vi1::MOI.VariableIndex, @@ -250,50 +174,6 @@ function standard_form(func::MatrixScalarQuadraticFunction{T}) where {T} return convert(MOI.ScalarQuadraticFunction{T}, func) end -""" - MatrixVectorAffineFunction{T, VT} <: MOI.AbstractVectorFunction - -Represents the function `terms * x + constant` -as an `MOI.AbstractVectorFunction` where `x[i] = MOI.VariableIndex(i)`. -Use [`standard_form`](@ref) to convert it to a `MOI.VectorAffineFunction{T}`. -""" -struct MatrixVectorAffineFunction{AT,VT} <: MOI.AbstractVectorFunction - terms::AT - constants::VT -end - -MOI.constant(func::MatrixVectorAffineFunction) = func.constants - -function Base.convert( - ::Type{MOI.VectorAffineFunction{T}}, - func::MatrixVectorAffineFunction, -) where {T} - return MOI.VectorAffineFunction{T}( - MOI.VectorAffineTerm{T}[ - # TODO we should do better if the matrix is a `SparseMatrixCSC` - MOI.VectorAffineTerm( - i, - MOI.ScalarAffineTerm{T}(func.terms[i, j], MOI.VariableIndex(j)), - ) for i in 1:size(func.terms, 1) for - j in 1:size(func.terms, 2) if !iszero(func.terms[i, j]) - ], - func.constants, - ) -end - -function standard_form(func::MatrixVectorAffineFunction{T}) where {T} - return convert(MOI.VectorAffineFunction{T}, func) -end - -# Only used for testing at the moment so performance is not critical so -# converting to standard form is ok -function MOI.Utilities.isapprox_zero( - func::Union{VectorScalarAffineFunction,MatrixScalarQuadraticFunction}, - tol, -) - return MOI.Utilities.isapprox_zero(standard_form(func), tol) -end - """ IndexMappedFunction{F<:MOI.AbstractFunction} <: AbstractLazyScalarFunction diff --git a/src/utils.jl b/src/utils.jl index ab1cb1d9..56278a75 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -152,6 +152,92 @@ function sparse_array_representation( ) end +# In the future, we could replace by https://github.com/jump-dev/MathOptInterface.jl/pull/1238 +""" + VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction + +Represents the function `x ⋅ terms + constant` +as an `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. +Use [`standard_form`](@ref) to convert it to a `MOI.ScalarAffineFunction{T}`. +""" +struct VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction + terms::VT + constant::T +end +MOI.constant(func::VectorScalarAffineFunction) = func.constant +function JuMP.coefficient(func::VectorScalarAffineFunction, vi::MOI.VariableIndex) + return func.terms[vi.value] +end +function Base.convert(::Type{MOI.ScalarAffineFunction{T}}, func::VectorScalarAffineFunction) where {T} + return MOI.ScalarAffineFunction{T}( + # TODO we should do better if the vector is a `SparseVector`, I think + # I have some code working for both vector types in Polyhedra.jl + MOI.ScalarAffineTerm{T}[ + MOI.ScalarAffineTerm{T}(func.terms[i], VI(i)) + for i in eachindex(func.terms) if !iszero(func.terms[i]) + ], + func.constant, + ) +end +function standard_form(func::VectorScalarAffineFunction{T}) where {T} + return convert(MOI.ScalarAffineFunction{T}, func) +end + +function MOI.Utilities.operate(::typeof(-), ::Type{T}, func::VectorScalarAffineFunction{T}) where {T} + return VectorScalarAffineFunction(LazyArrays.ApplyArray(-, func.terms), -func.constant) +end + +""" + struct MatrixScalarQuadraticFunction{T, VT, MT} <: MOI.AbstractScalarFunction + affine::VectorScalarAffineFunction{T,VT} + terms::MT + end + +Represents the function `x' * terms * x / 2 + affine` as an +`MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. +Use [`standard_form`](@ref) to convert it to a `MOI.ScalarQuadraticFunction{T}`. +""" +struct MatrixScalarQuadraticFunction{T, VT, MT} <: MOI.AbstractScalarFunction + affine::VectorScalarAffineFunction{T,VT} + terms::MT +end +MOI.constant(func::MatrixScalarQuadraticFunction) = MOI.constant(func.affine) +function JuMP.coefficient(func::MatrixScalarQuadraticFunction, vi::MOI.VariableIndex) + return JuMP.coefficient(func.affine, vi) +end + +""" + MatrixVectorAffineFunction{T, VT} <: MOI.AbstractVectorFunction + +Represents the function `terms * x + constant` +as an `MOI.AbstractVectorFunction` where `x[i] = MOI.VariableIndex(i)`. +Use [`standard_form`](@ref) to convert it to a `MOI.VectorAffineFunction{T}`. +""" +struct MatrixVectorAffineFunction{AT, VT} <: MOI.AbstractVectorFunction + terms::AT + constants::VT +end +MOI.constant(func::MatrixVectorAffineFunction) = func.constants +function Base.convert(::Type{MOI.VectorAffineFunction{T}}, func::MatrixVectorAffineFunction) where {T} + return MOI.VectorAffineFunction{T}( + MOI.VectorAffineTerm{T}[ + # TODO we should do better if the matrix is a `SparseMatrixCSC` + MOI.VectorAffineTerm(i, MOI.ScalarAffineTerm{T}(func.terms[i, j], VI(j))) + for i in 1:size(func.terms, 1) for j in 1:size(func.terms, 2) if !iszero(func.terms[i, j]) + ], + func.constants, + ) +end +function standard_form(func::MatrixVectorAffineFunction{T}) where {T} + return convert(MOI.VectorAffineFunction{T}, func) +end + +# Only used for testing at the moment so performance is not critical so +# converting to standard form is ok +function MOIU.isapprox_zero(func::Union{VectorScalarAffineFunction,MatrixScalarQuadraticFunction}, tol) + return MOIU.isapprox_zero(standard_form(func), tol) +end + _scalar(::Type{<:MatrixVectorAffineFunction}) = VectorScalarAffineFunction _scalar(::Type{<:SparseVectorAffineFunction}) = SparseScalarAffineFunction From 6b76114c0911fd19a7c977169bb941d5de3f814f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Wed, 12 Apr 2023 09:35:43 +0200 Subject: [PATCH 6/9] format --- src/ConicProgram/ConicProgram.jl | 2 +- src/bridges.jl | 4 ++- src/utils.jl | 58 ++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/ConicProgram/ConicProgram.jl b/src/ConicProgram/ConicProgram.jl index d04d25c9..75ad4de9 100644 --- a/src/ConicProgram/ConicProgram.jl +++ b/src/ConicProgram/ConicProgram.jl @@ -419,7 +419,7 @@ function DiffOpt._get_dA( g = model.back_grad_cache.g πz = model.back_grad_cache.πz #return DiffOpt.lazy_combination(-, g, πz, n .+ i, 1:n) - return g[n .+ i] * πz[1:n]' - πz[n .+ i] * g[1:n]' + return g[n.+i] * πz[1:n]' - πz[n.+i] * g[1:n]' end function MOI.get( diff --git a/src/bridges.jl b/src/bridges.jl index d4121f22..e1207c68 100644 --- a/src/bridges.jl +++ b/src/bridges.jl @@ -22,7 +22,9 @@ function MOI.get( attr::ReverseConstraintFunction, bridge::MOI.Bridges.Constraint.VectorizeBridge, ) - MOI.Utilities.eachscalar(MOI.get(model, attr, bridge.vector_constraint))[1] + return MOI.Utilities.eachscalar( + MOI.get(model, attr, bridge.vector_constraint), + )[1] end function MOI.get( model::MOI.ModelLike, diff --git a/src/utils.jl b/src/utils.jl index 56278a75..0f6aa4d3 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -160,21 +160,27 @@ Represents the function `x ⋅ terms + constant` as an `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. Use [`standard_form`](@ref) to convert it to a `MOI.ScalarAffineFunction{T}`. """ -struct VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction +struct VectorScalarAffineFunction{T,VT} <: MOI.AbstractScalarFunction terms::VT constant::T end MOI.constant(func::VectorScalarAffineFunction) = func.constant -function JuMP.coefficient(func::VectorScalarAffineFunction, vi::MOI.VariableIndex) +function JuMP.coefficient( + func::VectorScalarAffineFunction, + vi::MOI.VariableIndex, +) return func.terms[vi.value] end -function Base.convert(::Type{MOI.ScalarAffineFunction{T}}, func::VectorScalarAffineFunction) where {T} +function Base.convert( + ::Type{MOI.ScalarAffineFunction{T}}, + func::VectorScalarAffineFunction, +) where {T} return MOI.ScalarAffineFunction{T}( # TODO we should do better if the vector is a `SparseVector`, I think # I have some code working for both vector types in Polyhedra.jl MOI.ScalarAffineTerm{T}[ - MOI.ScalarAffineTerm{T}(func.terms[i], VI(i)) - for i in eachindex(func.terms) if !iszero(func.terms[i]) + MOI.ScalarAffineTerm{T}(func.terms[i], VI(i)) for + i in eachindex(func.terms) if !iszero(func.terms[i]) ], func.constant, ) @@ -183,8 +189,15 @@ function standard_form(func::VectorScalarAffineFunction{T}) where {T} return convert(MOI.ScalarAffineFunction{T}, func) end -function MOI.Utilities.operate(::typeof(-), ::Type{T}, func::VectorScalarAffineFunction{T}) where {T} - return VectorScalarAffineFunction(LazyArrays.ApplyArray(-, func.terms), -func.constant) +function MOI.Utilities.operate( + ::typeof(-), + ::Type{T}, + func::VectorScalarAffineFunction{T}, +) where {T} + return VectorScalarAffineFunction( + LazyArrays.ApplyArray(-, func.terms), + -func.constant, + ) end """ @@ -197,12 +210,15 @@ Represents the function `x' * terms * x / 2 + affine` as an `MOI.AbstractScalarFunction` where `x[i] = MOI.VariableIndex(i)`. Use [`standard_form`](@ref) to convert it to a `MOI.ScalarQuadraticFunction{T}`. """ -struct MatrixScalarQuadraticFunction{T, VT, MT} <: MOI.AbstractScalarFunction +struct MatrixScalarQuadraticFunction{T,VT,MT} <: MOI.AbstractScalarFunction affine::VectorScalarAffineFunction{T,VT} terms::MT end MOI.constant(func::MatrixScalarQuadraticFunction) = MOI.constant(func.affine) -function JuMP.coefficient(func::MatrixScalarQuadraticFunction, vi::MOI.VariableIndex) +function JuMP.coefficient( + func::MatrixScalarQuadraticFunction, + vi::MOI.VariableIndex, +) return JuMP.coefficient(func.affine, vi) end @@ -213,17 +229,23 @@ Represents the function `terms * x + constant` as an `MOI.AbstractVectorFunction` where `x[i] = MOI.VariableIndex(i)`. Use [`standard_form`](@ref) to convert it to a `MOI.VectorAffineFunction{T}`. """ -struct MatrixVectorAffineFunction{AT, VT} <: MOI.AbstractVectorFunction +struct MatrixVectorAffineFunction{AT,VT} <: MOI.AbstractVectorFunction terms::AT constants::VT end MOI.constant(func::MatrixVectorAffineFunction) = func.constants -function Base.convert(::Type{MOI.VectorAffineFunction{T}}, func::MatrixVectorAffineFunction) where {T} +function Base.convert( + ::Type{MOI.VectorAffineFunction{T}}, + func::MatrixVectorAffineFunction, +) where {T} return MOI.VectorAffineFunction{T}( MOI.VectorAffineTerm{T}[ # TODO we should do better if the matrix is a `SparseMatrixCSC` - MOI.VectorAffineTerm(i, MOI.ScalarAffineTerm{T}(func.terms[i, j], VI(j))) - for i in 1:size(func.terms, 1) for j in 1:size(func.terms, 2) if !iszero(func.terms[i, j]) + MOI.VectorAffineTerm( + i, + MOI.ScalarAffineTerm{T}(func.terms[i, j], VI(j)), + ) for i in 1:size(func.terms, 1) for + j in 1:size(func.terms, 2) if !iszero(func.terms[i, j]) ], func.constants, ) @@ -234,7 +256,10 @@ end # Only used for testing at the moment so performance is not critical so # converting to standard form is ok -function MOIU.isapprox_zero(func::Union{VectorScalarAffineFunction,MatrixScalarQuadraticFunction}, tol) +function MOIU.isapprox_zero( + func::Union{VectorScalarAffineFunction,MatrixScalarQuadraticFunction}, + tol, +) return MOIU.isapprox_zero(standard_form(func), tol) end @@ -245,10 +270,7 @@ function Base.getindex( it::MOI.Utilities.ScalarFunctionIterator{F}, output_index::Integer, ) where {F<:Union{MatrixVectorAffineFunction,SparseVectorAffineFunction}} - return _scalar(F)( - it.f.terms[output_index, :], - it.f.constants[output_index], - ) + return _scalar(F)(it.f.terms[output_index, :], it.f.constants[output_index]) end function _index_map_to_oneto!(index_map, v::MOI.VariableIndex) From 743d193fcddd0cb7bfb30b3259862f11cda8cf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 14 Apr 2023 18:13:27 +0200 Subject: [PATCH 7/9] Fixes --- src/utils.jl | 4 ++-- test/linear_program.jl | 4 ++-- test/utils.jl | 10 ++++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 0f6aa4d3..837096fc 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -179,7 +179,7 @@ function Base.convert( # TODO we should do better if the vector is a `SparseVector`, I think # I have some code working for both vector types in Polyhedra.jl MOI.ScalarAffineTerm{T}[ - MOI.ScalarAffineTerm{T}(func.terms[i], VI(i)) for + MOI.ScalarAffineTerm{T}(func.terms[i], MOI.VariableIndex(i)) for i in eachindex(func.terms) if !iszero(func.terms[i]) ], func.constant, @@ -243,7 +243,7 @@ function Base.convert( # TODO we should do better if the matrix is a `SparseMatrixCSC` MOI.VectorAffineTerm( i, - MOI.ScalarAffineTerm{T}(func.terms[i, j], VI(j)), + MOI.ScalarAffineTerm{T}(func.terms[i, j], MOI.VariableIndex(j)), ) for i in 1:size(func.terms, 1) for j in 1:size(func.terms, 2) if !iszero(func.terms[i, j]) ], diff --git a/test/linear_program.jl b/test/linear_program.jl index aa90ed8d..6d7f709e 100644 --- a/test/linear_program.jl +++ b/test/linear_program.jl @@ -12,8 +12,8 @@ import Ipopt import MathOptInterface as MOI import SCS -const ATOL = 2e-4 -const RTOL = 2e-4 +const ATOL = 1e-2 +const RTOL = 1e-2 function runtests() for name in names(@__MODULE__; all = true) diff --git a/test/utils.jl b/test/utils.jl index 9f957405..78edca0a 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -40,6 +40,7 @@ function qp_test( lt::Bool, set_zero::Bool, canonicalize::Bool; + known_sol = false, dzb = nothing, n = length(dzb), q = nothing, @@ -336,11 +337,14 @@ function qp_test( return end -function qp_test(solver, lt, set_zero, canonicalize; kws...) +function qp_test(solver, lt, set_zero, canonicalize; known_sol, kws...) @testset "With $diff_model" for diff_model in [ - DiffOpt.ConicProgram.Model, DiffOpt.QuadraticProgram.Model, + DiffOpt.ConicProgram.Model, ] + if diff_model === DiffOpt.ConicProgram.Model && known_sol + continue # FIXME + end qp_test(solver, diff_model, lt, set_zero, canonicalize; kws...) end return @@ -400,6 +404,7 @@ function qp_test_with_solutions( @testset "Without known solutions" begin qp_test( solver; + known_sol = false, dzb = dzb, q = q, dqf = dqf, @@ -424,6 +429,7 @@ function qp_test_with_solutions( @testset "With known solutions" begin qp_test( solver; + known_sol = true, dzb = dzb, q = q, dqf = dqf, From cea364e62c1418483efd8679044e4959b98f6080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 14 Apr 2023 18:35:36 +0200 Subject: [PATCH 8/9] Small refactor --- test/utils.jl | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/test/utils.jl b/test/utils.jl index 78edca0a..41352a5e 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -40,7 +40,6 @@ function qp_test( lt::Bool, set_zero::Bool, canonicalize::Bool; - known_sol = false, dzb = nothing, n = length(dzb), q = nothing, @@ -337,20 +336,7 @@ function qp_test( return end -function qp_test(solver, lt, set_zero, canonicalize; known_sol, kws...) - @testset "With $diff_model" for diff_model in [ - DiffOpt.QuadraticProgram.Model, - DiffOpt.ConicProgram.Model, - ] - if diff_model === DiffOpt.ConicProgram.Model && known_sol - continue # FIXME - end - qp_test(solver, diff_model, lt, set_zero, canonicalize; kws...) - end - return -end - -function qp_test(solver; kws...) +function qp_test(solver, diff_model; kws...) @testset "With $(lt ? "LessThan" : "GreaterThan") constraints" for lt in [ true, false, @@ -365,13 +351,23 @@ function qp_test(solver; kws...) true, false, ] - qp_test(solver, lt, set_zero, canonicalize; kws...) + qp_test(solver, diff_model, lt, set_zero, canonicalize; kws...) end end end return end +function qp_test(solver; kws...) + @testset "With $diff_model" for diff_model in [ + DiffOpt.QuadraticProgram.Model, + DiffOpt.ConicProgram.Model, + ] + qp_test(solver, diff_model; kws...) + end + return +end + function qp_test_with_solutions( solver; dzb = nothing, @@ -404,7 +400,6 @@ function qp_test_with_solutions( @testset "Without known solutions" begin qp_test( solver; - known_sol = false, dzb = dzb, q = q, dqf = dqf, @@ -428,8 +423,8 @@ function qp_test_with_solutions( end @testset "With known solutions" begin qp_test( - solver; - known_sol = true, + solver, + DiffOpt.QuadraticProgram.Model; # FIXME conic finds different solutions dzb = dzb, q = q, dqf = dqf, From 1bc4cad65f183f39a811ec58cb90488a92997a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Mon, 17 Apr 2023 10:15:34 +0200 Subject: [PATCH 9/9] Fix --- test/quadratic_program.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/quadratic_program.jl b/test/quadratic_program.jl index 4e535835..355110e4 100644 --- a/test/quadratic_program.jl +++ b/test/quadratic_program.jl @@ -322,6 +322,7 @@ function test_differentiating_non_trivial_convex_qp_moi() dbb = vec(grads_actual[6]) qp_test( Ipopt.Optimizer, + DiffOpt.ConicProgram.Model, true, true, true;