Skip to content

Commit fb285e6

Browse files
authored
Merge pull request #7 from JuliaOptimizationVariationalAnalysis/add-api-test
Add api tests
2 parents a5c9ab4 + c0eb116 commit fb285e6

File tree

4 files changed

+52
-151
lines changed

4 files changed

+52
-151
lines changed

Project.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ FastClosures = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a"
99
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
1111
NLPModels = "a4795742-8479-5a88-8948-cc11e1c8c1a6"
12+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1213
Stopping = "c4fe5a9e-e7fb-5c3d-89d5-7f405ab2214f"
1314

1415
[compat]

src/VariationalInequalitySolver.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module VariationalInequalitySolver
22

3-
using FastClosures, LinearAlgebra, Logging, NLPModels, Stopping
3+
using FastClosures, LinearAlgebra, Logging, NLPModels, SparseArrays, Stopping
44

55
import NLPModels:
66
residual!,

src/model/api.jl

+26-150
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ export jtprod_residual, jtprod_residual!, jac_op_residual, jac_op_residual!
44
export hess_residual, hess_structure_residual, hess_structure_residual!
55
export hess_coord_residual!, hess_coord_residual, jth_hess_residual
66
export hprod_residual, hprod_residual!, hess_op_residual, hess_op_residual!
7-
export project!, project
7+
export project!, project, get_meta
88

99
"""
1010
Fx = residual(model, x)
1111
Computes ``F(x)``, the residual at x.
1212
"""
13-
function residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}) where {T, S}
13+
function NLPModels.residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}) where {T, S}
1414
@lencheck model.meta.nvar x
1515
Fx = S(undef, model.meta.nvar)
1616
residual!(model, x, Fx)
@@ -26,7 +26,7 @@ function residual! end
2626
Jx = jac_residual(model, x)
2727
Computes ``J(x)``, the Jacobian of the residual at x.
2828
"""
29-
function jac_residual(model::AbstractVIModel, x::AbstractVector)
29+
function NLPModels.jac_residual(model::AbstractVIModel, x::AbstractVector)
3030
@lencheck model.meta.nvar x
3131
rows, cols = jac_structure_residual(model)
3232
vals = jac_coord_residual(model, x)
@@ -43,9 +43,9 @@ function jac_structure_residual! end
4343
(rows,cols) = jac_structure_residual(model)
4444
Returns the structure of the constraint's Jacobian in sparse coordinate format.
4545
"""
46-
function jac_structure_residual(model::AbstractVIModel)
47-
rows = Vector{Int}(undef, model.nnzj)
48-
cols = Vector{Int}(undef, model.nnzj)
46+
function NLPModels.jac_structure_residual(model::AbstractVIModel)
47+
rows = Vector{Int}(undef, model.meta.nnzj)
48+
cols = Vector{Int}(undef, model.meta.nnzj)
4949
jac_structure_residual!(model, rows, cols)
5050
end
5151

@@ -60,17 +60,17 @@ function jac_coord_residual! end
6060
(rows,cols,vals) = jac_coord_residual(model, x)
6161
Computes the Jacobian of the residual at `x` in sparse coordinate format.
6262
"""
63-
function jac_coord_residual(model::AbstractVIModel, x::AbstractVector)
63+
function NLPModels.jac_coord_residual(model::AbstractVIModel, x::AbstractVector)
6464
@lencheck model.meta.nvar x
65-
vals = Vector{eltype(x)}(undef, model.nnzj)
65+
vals = Vector{eltype(x)}(undef, model.meta.nnzj)
6666
jac_coord_residual!(model, x, vals)
6767
end
6868

6969
"""
7070
Jv = jprod_residual(model, x, v)
7171
Computes the product of the Jacobian of the residual at x and a vector, i.e., ``J(x)v``.
7272
"""
73-
function jprod_residual(
73+
function NLPModels.jprod_residual(
7474
model::AbstractVIModel{T, S},
7575
x::AbstractVector{T},
7676
v::AbstractVector,
@@ -91,43 +91,25 @@ function jprod_residual! end
9191
Computes the product of the Jacobian of the residual given by `(rows, cols, vals)`
9292
and a vector, i.e., ``J(x)v``, storing it in `Jv`.
9393
"""
94-
function jprod_residual!(
94+
function NLPModels.jprod_residual!(
9595
model::AbstractVIModel,
9696
rows::AbstractVector{<:Integer},
9797
cols::AbstractVector{<:Integer},
9898
vals::AbstractVector,
9999
v::AbstractVector,
100100
Jv::AbstractVector,
101101
)
102-
@lencheck model.nnzj rows cols vals
102+
@lencheck model.meta.nnzj rows cols vals
103103
@lencheck model.meta.nvar v Jv
104104
increment!(model, :neval_jprod_residual)
105105
coo_prod!(rows, cols, vals, v, Jv)
106106
end
107107

108-
"""
109-
Jv = jprod_residual!(model, x, rows, cols, v, Jv)
110-
Computes the product of the Jacobian of the residual at x and a vector, i.e., ``J(x)v``, storing it in `Jv`.
111-
The structure of the Jacobian is given by `(rows, cols)`.
112-
"""
113-
function jprod_residual!(
114-
model::AbstractVIModel,
115-
x::AbstractVector,
116-
rows::AbstractVector{<:Integer},
117-
cols::AbstractVector{<:Integer},
118-
v::AbstractVector,
119-
Jv::AbstractVector,
120-
)
121-
@lencheck model.meta.nvar x v Jv
122-
@lencheck model.nnzj rows cols
123-
jprod_residual!(model, x, v, Jv)
124-
end
125-
126108
"""
127109
Jtv = jtprod_residual(model, x, v)
128110
Computes the product of the transpose of the Jacobian of the residual at x and a vector, i.e., ``J(x)^Tv``.
129111
"""
130-
function jtprod_residual(
112+
function NLPModels.jtprod_residual(
131113
model::AbstractVIModel{T, S},
132114
x::AbstractVector{T},
133115
v::AbstractVector,
@@ -148,104 +130,45 @@ function jtprod_residual! end
148130
Computes the product of the transpose of the Jacobian of the residual given by `(rows, cols, vals)`
149131
and a vector, i.e., ``J(x)^Tv``, storing it in `Jv`.
150132
"""
151-
function jtprod_residual!(
133+
function NLPModels.jtprod_residual!(
152134
model::AbstractVIModel,
153135
rows::AbstractVector{<:Integer},
154136
cols::AbstractVector{<:Integer},
155137
vals::AbstractVector,
156138
v::AbstractVector,
157139
Jtv::AbstractVector,
158140
)
159-
@lencheck model.nnzj rows cols vals
141+
@lencheck model.meta.nnzj rows cols vals
160142
@lencheck model.meta.nvar v Jtv
161143
increment!(model, :neval_jtprod_residual)
162144
coo_prod!(cols, rows, vals, v, Jtv)
163145
end
164146

165-
"""
166-
Jtv = jtprod_residual!(model, x, rows, cols, v, Jtv)
167-
Computes the product of the transpose Jacobian of the residual at x and a vector, i.e., ``J(x)^Tv``, storing it in `Jv`.
168-
The structure of the Jacobian is given by `(rows, cols)`.
169-
"""
170-
function jtprod_residual!(
171-
model::AbstractVIModel,
172-
x::AbstractVector,
173-
rows::AbstractVector{<:Integer},
174-
cols::AbstractVector{<:Integer},
175-
v::AbstractVector,
176-
Jtv::AbstractVector,
177-
)
178-
@lencheck model.meta.nvar x v Jtv
179-
@lencheck model.nnzj rows cols
180-
jtprod_residual!(model, x, v, Jtv)
181-
end
182-
183147
"""
184148
Jx = jac_op_residual(model, x)
185149
Computes ``J(x)``, the Jacobian of the residual at x, in linear operator form.
186150
"""
187-
function jac_op_residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}) where {T, S}
151+
function NLPModels.jac_op_residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}) where {T, S}
188152
@lencheck model.meta.nvar x
189153
Jv = S(undef, model.meta.nvar)
190154
Jtv = S(undef, model.meta.nvar)
191155
return jac_op_residual!(model, x, Jv, Jtv)
192156
end
193157

194-
"""
195-
Jx = jac_op_residual!(model, x, Jv, Jtv)
196-
Computes ``J(x)``, the Jacobian of the residual at x, in linear operator form. The
197-
vectors `Jv` and `Jtv` are used as preallocated storage for the operations.
198-
"""
199-
function jac_op_residual!(
200-
model::AbstractVIModel,
201-
x::AbstractVector,
202-
Jv::AbstractVector,
203-
Jtv::AbstractVector,
204-
)
205-
@lencheck model.meta.nvar x Jv Jtv
206-
prod! = @closure (res, v, α, β) -> begin
207-
jprod_residual!(model, x, v, Jv)
208-
if β == 0
209-
@. res = α * Jv
210-
else
211-
@. res = α * Jv + β * res
212-
end
213-
return res
214-
end
215-
ctprod! = @closure (res, v, α, β) -> begin
216-
jtprod_residual!(model, x, v, Jtv)
217-
if β == 0
218-
@. res = α * Jtv
219-
else
220-
@. res = α * Jtv + β * res
221-
end
222-
return res
223-
end
224-
return LinearOperator{eltype(x)}(
225-
model.meta.nvar,
226-
model.meta.nvar,
227-
false,
228-
false,
229-
prod!,
230-
ctprod!,
231-
ctprod!,
232-
)
233-
end
234-
235158
"""
236159
Jx = jac_op_residual!(model, rows, cols, vals, Jv, Jtv)
237160
Computes ``J(x)``, the Jacobian of the residual given by `(rows, cols, vals)`, in linear operator form. The
238161
vectors `Jv` and `Jtv` are used as preallocated storage for the operations.
239162
"""
240-
function jac_op_residual!(
163+
function NLPModels.jac_op_residual!(
241164
model::AbstractVIModel,
242165
rows::AbstractVector{<:Integer},
243166
cols::AbstractVector{<:Integer},
244167
vals::AbstractVector,
245168
Jv::AbstractVector,
246169
Jtv::AbstractVector,
247170
)
248-
@lencheck model.nnzj rows cols vals
171+
@lencheck model.meta.nnzj rows cols vals
249172
@lencheck model.meta.nvar Jv Jtv
250173
prod! = @closure (res, v, α, β) -> begin
251174
jprod_residual!(model, rows, cols, vals, v, Jv)
@@ -276,34 +199,13 @@ function jac_op_residual!(
276199
)
277200
end
278201

279-
"""
280-
Jx = jac_op_residual!(model, x, rows, cols, Jv, Jtv)
281-
Computes ``J(x)``, the Jacobian of the residual at x, in linear operator form. The
282-
vectors `Jv` and `Jtv` are used as preallocated storage for the operations.
283-
The structure of the Jacobian should be given by `(rows, cols)`.
284-
"""
285-
function jac_op_residual!(
286-
model::AbstractVIModel,
287-
x::AbstractVector,
288-
rows::AbstractVector{<:Integer},
289-
cols::AbstractVector{<:Integer},
290-
Jv::AbstractVector,
291-
Jtv::AbstractVector,
292-
)
293-
@lencheck model.meta.nvar x Jv Jtv
294-
@lencheck model.nnzj rows cols
295-
vals = jac_coord_residual(model, x)
296-
decrement!(model, :neval_jac_residual)
297-
return jac_op_residual!(model, rows, cols, vals, Jv, Jtv)
298-
end
299-
300202
"""
301203
H = hess_residual(model, x, v)
302204
Computes the linear combination of the Hessians of the residuals at `x` with coefficients
303205
`v`.
304206
A `Symmetric` object wrapping the lower triangle is returned.
305207
"""
306-
function hess_residual(model::AbstractVIModel, x::AbstractVector, v::AbstractVector)
208+
function NLPModels.hess_residual(model::AbstractVIModel, x::AbstractVector, v::AbstractVector)
307209
@lencheck model.meta.nvar x v
308210
rows, cols = hess_structure_residual(model)
309211
vals = hess_coord_residual(model, x, v)
@@ -314,9 +216,9 @@ end
314216
(rows,cols) = hess_structure_residual(model)
315217
Returns the structure of the residual Hessian.
316218
"""
317-
function hess_structure_residual(model::AbstractVIModel)
318-
rows = Vector{Int}(undef, model.nnzh)
319-
cols = Vector{Int}(undef, model.nnzh)
219+
function NLPModels.hess_structure_residual(model::AbstractVIModel)
220+
rows = Vector{Int}(undef, model.meta.nnzh)
221+
cols = Vector{Int}(undef, model.meta.nnzh)
320222
hess_structure_residual!(model, rows, cols)
321223
end
322224

@@ -338,17 +240,17 @@ function hess_coord_residual! end
338240
Computes the linear combination of the Hessians of the residuals at `x` with coefficients
339241
`v` in sparse coordinate format.
340242
"""
341-
function hess_coord_residual(model::AbstractVIModel, x::AbstractVector, v::AbstractVector)
243+
function NLPModels.hess_coord_residual(model::AbstractVIModel, x::AbstractVector, v::AbstractVector)
342244
@lencheck model.meta.nvar x v
343-
vals = Vector{eltype(x)}(undef, model.nnzh)
245+
vals = Vector{eltype(x)}(undef, model.meta.nnzh)
344246
hess_coord_residual!(model, x, v, vals)
345247
end
346248

347249
"""
348250
Hj = jth_hess_residual(model, x, j)
349251
Computes the Hessian of the j-th residual at x.
350252
"""
351-
function jth_hess_residual(model::AbstractVIModel, x::AbstractVector, j::Int)
253+
function NLPModels.jth_hess_residual(model::AbstractVIModel, x::AbstractVector, j::Int)
352254
@lencheck model.meta.nvar x
353255
increment!(model, :neval_jhess_residual)
354256
decrement!(model, :neval_hess_residual)
@@ -360,7 +262,7 @@ end
360262
Hiv = hprod_residual(model, x, i, v)
361263
Computes the product of the Hessian of the i-th residual at x, times the vector v.
362264
"""
363-
function hprod_residual(
265+
function NLPModels.hprod_residual(
364266
model::AbstractVIModel{T, S},
365267
x::AbstractVector{T},
366268
i::Int,
@@ -381,38 +283,12 @@ function hprod_residual! end
381283
Hop = hess_op_residual(model, x, i)
382284
Computes the Hessian of the i-th residual at x, in linear operator form.
383285
"""
384-
function hess_op_residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}, i::Int) where {T, S}
286+
function NLPModels.hess_op_residual(model::AbstractVIModel{T, S}, x::AbstractVector{T}, i::Int) where {T, S}
385287
@lencheck model.meta.nvar x
386288
Hiv = S(undef, model.meta.nvar)
387289
return hess_op_residual!(model, x, i, Hiv)
388290
end
389291

390-
"""
391-
Hop = hess_op_residual!(model, x, i, Hiv)
392-
Computes the Hessian of the i-th residual at x, in linear operator form. The vector `Hiv` is used as preallocated storage for the operation.
393-
"""
394-
function hess_op_residual!(model::AbstractVIModel, x::AbstractVector, i::Int, Hiv::AbstractVector)
395-
@lencheck model.meta.nvar x Hiv
396-
prod! = @closure (res, v, α, β) -> begin
397-
hprod_residual!(model, x, i, v, Hiv)
398-
if β == 0
399-
@. res = α * Hiv
400-
else
401-
@. res = α * Hiv + β * res
402-
end
403-
return res
404-
end
405-
return LinearOperator{eltype(x)}(
406-
model.meta.nvar,
407-
model.meta.nvar,
408-
true,
409-
true,
410-
prod!,
411-
prod!,
412-
prod!,
413-
)
414-
end
415-
416292
get_meta(model::AbstractVIModel) = model.meta
417293

418294
"""

test/runtests.jl

+24
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,27 @@ Random.seed!(1234)
1111
@test project(vi, xr) == xr
1212
sol = ProjectionVI(vi, xr)
1313
end
14+
15+
@testset "Test API AbstractVIModel" begin
16+
for T in [Float16, Float32, Float64]
17+
nls = ADNLSModel(x -> [x[1] - 1; 10 * (x[2] - x[1]^2)], T[-1.2; 1.0], 2)
18+
vi = NLSVIModel(nls)
19+
20+
@test get_meta(vi) == vi.meta
21+
22+
xr = ones(T, 2)
23+
@test residual(vi, xr) == T[0; 0]
24+
J = T[ 1 0; -20 10]
25+
@test jac_residual(vi, xr) == J
26+
v = ones(T, 2)
27+
@test jprod_residual(vi, xr, v) == T[1; -10]
28+
@test jtprod_residual(vi, xr, v) == T[-19; 10]
29+
J = jac_op_residual(vi, xr)
30+
@test J * v == T[1; -10]
31+
@test J' * v == T[-19; 10]
32+
@test hess_residual(vi, xr, xr) == T[-20 0; 0 0]
33+
@test hprod_residual(vi, xr, 2, v) == T[-20; 0]
34+
H = hess_op_residual(vi, xr, 2)
35+
@test H * v == T[-20; 0]
36+
end
37+
end

0 commit comments

Comments
 (0)