From 66d335765b666c284f4bb23c4d8fdf7148e99107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 31 Jul 2025 11:28:47 +0200 Subject: [PATCH 1/2] Define our own functions when methods does not match NLPModels --- src/BurerMonteiro.jl | 40 ++++++++++++++++++++-------------------- src/buffer.jl | 12 ++++++------ src/errors.jl | 4 ++-- src/model.jl | 21 ++++++++++----------- test/diff_check.jl | 8 ++++---- test/maxcut.jl | 10 +++++----- 6 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/BurerMonteiro.jl b/src/BurerMonteiro.jl index 830f0fb..a91f00a 100644 --- a/src/BurerMonteiro.jl +++ b/src/BurerMonteiro.jl @@ -152,24 +152,24 @@ function NLPModels.obj(model::Model, x::AbstractVector) return NLPModels.obj(model.model, Solution(x, model.dim)) end -function NLPModels.grad!(model::Model{false}, _, g, ::Type{LRO.ScalarIndex}) - return copyto!(g, NLPModels.grad(model.model, LRO.ScalarIndex)) +function grad!(model::Model{false}, _, g, ::Type{LRO.ScalarIndex}) + return copyto!(g, LRO.grad(model.model, LRO.ScalarIndex)) end -function NLPModels.grad!(model::Model{true}, x, g, ::Type{LRO.ScalarIndex}) +function grad!(model::Model{true}, x, g, ::Type{LRO.ScalarIndex}) g .= - 2 .* NLPModels.grad(model.model, LRO.ScalarIndex) .* + 2 .* LRO.grad(model.model, LRO.ScalarIndex) .* LRO.left_factor(x, LRO.ScalarIndex) return g end -function NLPModels.grad!( +function grad!( model::Model, X::LRO.Factorization, G::LRO.Factorization, i::LRO.MatrixIndex, ) - C = NLPModels.grad(model.model, i) + C = LRO.grad(model.model, i) LinearAlgebra.mul!(G.factor, C, X.factor) G.factor .*= 2 return @@ -178,14 +178,14 @@ end function NLPModels.grad!(model::Model, x::AbstractVector, g::AbstractVector) X = Solution(x, model.dim) G = Solution(g, model.dim) - NLPModels.grad!( + grad!( model, X, LRO.left_factor(G, LRO.ScalarIndex), LRO.ScalarIndex, ) for i in LRO.matrix_indices(model.model) - NLPModels.grad!(model, X[i], G[i], i) + grad!(model, X[i], G[i], i) end return g end @@ -222,7 +222,7 @@ function NLPModels.jprod!( return NLPModels.jprod!(model.model, X, _OuterProduct(X, V), Jv) end -function NLPModels.jtprod!( +function jtprod!( model::Model{false}, _, y::AbstractVector, @@ -231,19 +231,19 @@ function NLPModels.jtprod!( ) return LinearAlgebra.mul!( JtV, - NLPModels.jac(model.model, LRO.ScalarIndex)', + LRO.jac(model.model, LRO.ScalarIndex)', y, ) end -function NLPModels.jtprod!( +function jtprod!( model::Model{true}, X, y::AbstractVector, JtV::AbstractVector, ::Type{LRO.ScalarIndex}, ) - LinearAlgebra.mul!(JtV, NLPModels.jac(model.model, LRO.ScalarIndex)', y) + LinearAlgebra.mul!(JtV, LRO.jac(model.model, LRO.ScalarIndex)', y) JtV .*= 2 .* LRO.left_factor(X, LRO.ScalarIndex) return JtV end @@ -256,12 +256,12 @@ function add_jtprod!( i::LRO.MatrixIndex, ) for j in eachindex(y) - A = NLPModels.jac(model.model, j, i) + A = LRO.jac(model.model, j, i) LinearAlgebra.mul!(JtV.factor, A, X.factor, 2y[j], true) end end -function NLPModels.jtprod!( +function jtprod!( model::Model, X, y::AbstractVector, @@ -280,7 +280,7 @@ function NLPModels.jtprod!( ) X = Solution(x, model.dim) JtV = Solution(Jtv, model.dim) - NLPModels.jtprod!( + jtprod!( model, X, y, @@ -288,7 +288,7 @@ function NLPModels.jtprod!( LRO.ScalarIndex, ) for i in LRO.matrix_indices(model.model) - NLPModels.jtprod!(model, X[i], y, JtV[i], i) + jtprod!(model, X[i], y, JtV[i], i) end return Jtv end @@ -314,10 +314,10 @@ function NLPModels.hprod!( ::Type{LRO.ScalarIndex}; obj_weight, ) where {T} - Hv .= obj_weight .* NLPModels.grad(model.model, LRO.ScalarIndex) + Hv .= obj_weight .* LRO.grad(model.model, LRO.ScalarIndex) LinearAlgebra.mul!( Hv, - NLPModels.jac(model.model, LRO.ScalarIndex)', + LRO.jac(model.model, LRO.ScalarIndex)', y, true, true, @@ -347,11 +347,11 @@ function NLPModels.hprod!( ) for i in LRO.matrix_indices(model.model) Vi = V[i].factor - C = NLPModels.grad(model.model, i) + C = LRO.grad(model.model, i) Hvi = HV[i].factor LinearAlgebra.mul!(Hvi, C, Vi, 2obj_weight, false) for j in 1:model.meta.ncon - A = NLPModels.jac(model.model, j, i) + A = LRO.jac(model.model, j, i) LinearAlgebra.mul!(Hvi, A, Vi, -2y[j], true) end end diff --git a/src/buffer.jl b/src/buffer.jl index 90d5678..fda7416 100644 --- a/src/buffer.jl +++ b/src/buffer.jl @@ -40,12 +40,12 @@ function dual_obj(model::BufferedModelForSchur, y::AbstractVector) return dual_obj(model.model, y) end -function NLPModels.grad(model::BufferedModelForSchur, ::Type{ScalarIndex}) - return NLPModels.grad(model.model, ScalarIndex) +function grad(model::BufferedModelForSchur, ::Type{ScalarIndex}) + return grad(model.model, ScalarIndex) end -function NLPModels.grad(model::BufferedModelForSchur, i::MatrixIndex) - return NLPModels.grad(model.model, i) +function grad(model::BufferedModelForSchur, i::MatrixIndex) + return grad(model.model, i) end ######################### @@ -53,12 +53,12 @@ end ######################### cons_constant(model::BufferedModelForSchur) = cons_constant(model.model) -function NLPModels.jac( +function jac( model::BufferedModelForSchur, j::Integer, ::Type{ScalarIndex}, ) - return NLPModels.jac(model.model, j, ScalarIndex) + return jac(model.model, j, ScalarIndex) end function norm_jac(model::BufferedModelForSchur, i::MatrixIndex) return norm_jac(model.model, i) diff --git a/src/errors.jl b/src/errors.jl index 15f8ee3..1356eeb 100644 --- a/src/errors.jl +++ b/src/errors.jl @@ -16,9 +16,9 @@ function errors( b_den = 1 + LinearAlgebra.norm(cons_constant(model), 1) C_den = 1 + - LinearAlgebra.norm(NLPModels.grad(model, ScalarIndex), 1) + + LinearAlgebra.norm(grad(model, ScalarIndex), 1) + sum(matrix_indices(model), init = zero(b_den)) do i - return LinearAlgebra.norm(NLPModels.grad(model, i), 1) + return LinearAlgebra.norm(grad(model, i), 1) end obj_den = 1 + abs(pobj) + abs(dobj) return ( diff --git a/src/model.jl b/src/model.jl index e2a803c..1e4beb5 100644 --- a/src/model.jl +++ b/src/model.jl @@ -123,25 +123,24 @@ side_dimension(model::Model, i::MatrixIndex) = model.msizes[i.value] ###### Objective ###### ####################### -function NLPModels.obj(model::Model, X::AbstractMatrix, i::MatrixIndex) +function obj(model::Model, X::AbstractMatrix, i::MatrixIndex) return LinearAlgebra.dot(model.C[i.value], X) end -function NLPModels.obj(model::Model, x::AbstractVector, ::Type{MatrixIndex}) +function obj(model::Model, x::AbstractVector, ::Type{MatrixIndex}) result = zero(eltype(x)) for i in matrix_indices(model) - result += NLPModels.obj(model, x[i], i) + result += obj(model, x[i], i) end return result end -function NLPModels.obj(model::Model, x::AbstractVector, ::Type{ScalarIndex}) +function obj(model::Model, x::AbstractVector, ::Type{ScalarIndex}) return LinearAlgebra.dot(model.d_lin, x[ScalarIndex]) end function NLPModels.obj(model::Model, x::AbstractVector) - return NLPModels.obj(model, x, MatrixIndex) + - NLPModels.obj(model, x, ScalarIndex) + return obj(model, x, ScalarIndex) + obj(model, x, MatrixIndex) end function NLPModels.grad!(model::Model, _::AbstractVector, g::AbstractVector) @@ -168,8 +167,8 @@ function dual_cons!(model::Model, y::AbstractVector, res, ::Type{ScalarIndex}) return LinearAlgebra.mul!(res, model.C_lin', y, -1, true) end -NLPModels.grad(model::Model, ::Type{ScalarIndex}) = model.d_lin -NLPModels.grad(model::Model, i::MatrixIndex) = model.C[i.value] +grad(model::Model, ::Type{ScalarIndex}) = model.d_lin +grad(model::Model, i::MatrixIndex) = model.C[i.value] ######################### ###### Constraints ###### @@ -178,11 +177,11 @@ NLPModels.grad(model::Model, i::MatrixIndex) = model.C[i.value] cons_constant(model::Model) = model.b # Should be only used with `norm` -NLPModels.jac(model::Model, ::Type{ScalarIndex}) = model.C_lin -function NLPModels.jac(model::Model, j::Integer, i::MatrixIndex) +jac(model::Model, ::Type{ScalarIndex}) = model.C_lin +function jac(model::Model, j::Integer, i::MatrixIndex) return model.A[i.value, j] end -function NLPModels.jac(model::Model, j::Integer, ::Type{ScalarIndex}) +function jac(model::Model, j::Integer, ::Type{ScalarIndex}) return model.C_lin[j, :] end function norm_jac(model::Model{T}, i::MatrixIndex) where {T} diff --git a/test/diff_check.jl b/test/diff_check.jl index 026a462..c4719ea 100644 --- a/test/diff_check.jl +++ b/test/diff_check.jl @@ -130,12 +130,12 @@ function schur_test(model::LRO.BufferedModelForSchur{T}, w) where {T} idx = LRO.matrix_indices(model) @test NLPModels.obj(model, w) ≈ - dot(NLPModels.grad(model, LRO.ScalarIndex), w[LRO.ScalarIndex]) + - dot(NLPModels.grad.(model, idx), getindex.(Ref(w), idx)) + dot(LRO.grad(model, LRO.ScalarIndex), w[LRO.ScalarIndex]) + + dot(LRO.grad.(model, idx), getindex.(Ref(w), idx)) @test LRO.dual_obj(model, y) ≈ dot(LRO.cons_constant(model), y) - @test NLPModels.jac(model, 1, LRO.ScalarIndex) == - NLPModels.jac(model.model, 1, LRO.ScalarIndex) + @test LRO.jac(model, 1, LRO.ScalarIndex) == + LRO.jac(model.model, 1, LRO.ScalarIndex) @test LRO.norm_jac.(model, idx) == LRO.norm_jac.(model.model, idx) @test LRO.side_dimension.(model, idx) == LRO.side_dimension.(model.model, idx) diff --git a/test/maxcut.jl b/test/maxcut.jl index b11a619..cd962f8 100644 --- a/test/maxcut.jl +++ b/test/maxcut.jl @@ -70,7 +70,7 @@ function test_maxcut(; is_dual, sparse, vector) diff_check(model) X = LRO.positive_semidefinite_factorization(rand(4)) JtV = LRO.positive_semidefinite_factorization(ones(4)) - NLPModels.grad!(solver.model, X, JtV, i) + LRO.BurerMonteiro.grad!(solver.model, X, JtV, i) @test JtV.factor ≈ 2lro_model.C[] * X.factor fill!(JtV.factor, 0.0) y = rand(lro_model.meta.ncon) @@ -113,16 +113,16 @@ end; [Matrix(x[i]) for i in LRO.matrix_indices(b.model)], ) y = collect(1:b.model.meta.ncon) - @test NLPModels.jac(b.model, 1, LRO.MatrixIndex(1)) == + @test LRO.jac(b.model, 1, LRO.MatrixIndex(1)) == sparse([1], [1], [-1], 4, 4) - @test NLPModels.jac(b.model, 1, LRO.ScalarIndex) == + @test LRO.jac(b.model, 1, LRO.ScalarIndex) == sparsevec([1, 2], [-1, 1], 8) @test LRO.norm_jac(b.model, LRO.MatrixIndex(1)) == 4 grad = similar(x) NLPModels.grad!(b.model, X, grad) @test Vector(grad) == [ - Vector(NLPModels.grad(b.model, LRO.ScalarIndex)); - NLPModels.grad(b.model, LRO.MatrixIndex(1))[:] + Vector(LRO.grad(b.model, LRO.ScalarIndex)); + LRO.grad(b.model, LRO.MatrixIndex(1))[:] ] for xx in [x, X] err = LRO.errors(b.solver.model, xx; y, dual_slack = xx, dual_err = xx) From f2966655f73fadbf99ae596503c7d3913abf5759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 31 Jul 2025 11:29:04 +0200 Subject: [PATCH 2/2] Fix format --- src/BurerMonteiro.jl | 21 +++------------------ src/buffer.jl | 6 +----- test/maxcut.jl | 3 +-- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/BurerMonteiro.jl b/src/BurerMonteiro.jl index a91f00a..9a41b7b 100644 --- a/src/BurerMonteiro.jl +++ b/src/BurerMonteiro.jl @@ -178,12 +178,7 @@ end function NLPModels.grad!(model::Model, x::AbstractVector, g::AbstractVector) X = Solution(x, model.dim) G = Solution(g, model.dim) - grad!( - model, - X, - LRO.left_factor(G, LRO.ScalarIndex), - LRO.ScalarIndex, - ) + grad!(model, X, LRO.left_factor(G, LRO.ScalarIndex), LRO.ScalarIndex) for i in LRO.matrix_indices(model.model) grad!(model, X[i], G[i], i) end @@ -229,11 +224,7 @@ function jtprod!( JtV::AbstractVector, ::Type{LRO.ScalarIndex}, ) - return LinearAlgebra.mul!( - JtV, - LRO.jac(model.model, LRO.ScalarIndex)', - y, - ) + return LinearAlgebra.mul!(JtV, LRO.jac(model.model, LRO.ScalarIndex)', y) end function jtprod!( @@ -280,13 +271,7 @@ function NLPModels.jtprod!( ) X = Solution(x, model.dim) JtV = Solution(Jtv, model.dim) - jtprod!( - model, - X, - y, - LRO.left_factor(JtV, LRO.ScalarIndex), - LRO.ScalarIndex, - ) + jtprod!(model, X, y, LRO.left_factor(JtV, LRO.ScalarIndex), LRO.ScalarIndex) for i in LRO.matrix_indices(model.model) jtprod!(model, X[i], y, JtV[i], i) end diff --git a/src/buffer.jl b/src/buffer.jl index fda7416..4675fec 100644 --- a/src/buffer.jl +++ b/src/buffer.jl @@ -53,11 +53,7 @@ end ######################### cons_constant(model::BufferedModelForSchur) = cons_constant(model.model) -function jac( - model::BufferedModelForSchur, - j::Integer, - ::Type{ScalarIndex}, -) +function jac(model::BufferedModelForSchur, j::Integer, ::Type{ScalarIndex}) return jac(model.model, j, ScalarIndex) end function norm_jac(model::BufferedModelForSchur, i::MatrixIndex) diff --git a/test/maxcut.jl b/test/maxcut.jl index cd962f8..6981f72 100644 --- a/test/maxcut.jl +++ b/test/maxcut.jl @@ -115,8 +115,7 @@ end; y = collect(1:b.model.meta.ncon) @test LRO.jac(b.model, 1, LRO.MatrixIndex(1)) == sparse([1], [1], [-1], 4, 4) - @test LRO.jac(b.model, 1, LRO.ScalarIndex) == - sparsevec([1, 2], [-1, 1], 8) + @test LRO.jac(b.model, 1, LRO.ScalarIndex) == sparsevec([1, 2], [-1, 1], 8) @test LRO.norm_jac(b.model, LRO.MatrixIndex(1)) == 4 grad = similar(x) NLPModels.grad!(b.model, X, grad)