Skip to content

Commit cb1ad41

Browse files
authored
[docs] improve docstrings in src/nlp.jl (#2537)
1 parent b5659b5 commit cb1ad41

File tree

4 files changed

+819
-66
lines changed

4 files changed

+819
-66
lines changed

docs/src/submodules/Test/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ Test.setup_test
1818
Test.version_added
1919
Test.@requires
2020
Test.RequirementUnmet
21+
Test.HS071
2122
```

src/Test/test_nonlinear.jl

Lines changed: 103 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
enable_hessian_vector_product::Bool = false,
1111
)
1212
13-
An AbstractNLPEvaluator for the problem:
14-
```
15-
min x1 * x4 * (x1 + x2 + x3) + x3
16-
st x1 * x2 * x3 * x4 >= 25
17-
x1^2 + x2^2 + x3^2 + x4^2 = 40
18-
1 <= x1, x2, x3, x4 <= 5
13+
An [`MOI.AbstractNLPEvaluator`](@ref) for the problem:
14+
15+
```math
16+
\\begin{aligned}
17+
\\text{min} \\ & x_1 * x_4 * (x_1 + x_2 + x_3) + x_3 \\\\
18+
\\text{subject to}\\ & x_1 * x_2 * x_3 * x_4 \\ge 25 \\\\
19+
& x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40 \\\\
20+
& 1 \\le x_1, x_2, x_3, x_4 \\le 5
21+
\\end{aligned}
1922
```
20-
Start at (1,5,5,1)
21-
End at (1.000..., 4.743..., 3.821..., 1.379...)
23+
24+
The optimal solution is `[1.000, 4.743, 3.821, 1.379]`.
2225
"""
2326
struct HS071 <: MOI.AbstractNLPEvaluator
2427
enable_hessian::Bool
@@ -35,13 +38,13 @@ function MOI.initialize(d::HS071, requested_features::Vector{Symbol})
3538
for feat in requested_features
3639
if !(feat in MOI.features_available(d))
3740
error("Unsupported feature $feat")
38-
# TODO: implement Jac-vec products for solvers that need them
3941
end
4042
end
43+
return
4144
end
4245

4346
function MOI.features_available(d::HS071)
44-
features = [:Grad, :Jac, :ExprGraph]
47+
features = [:Grad, :Jac, :JacVec, :ExprGraph]
4548
if d.enable_hessian
4649
push!(features, :Hess)
4750
end
@@ -99,6 +102,26 @@ function MOI.eval_objective_gradient(::HS071, grad_f, x)
99102
return
100103
end
101104

105+
function MOI.constraint_gradient_structure(::HS071, ::Int)
106+
return [1, 2, 3, 4]
107+
end
108+
109+
function MOI.eval_constraint_gradient(::HS071, ∇g, x, i)
110+
@assert 1 <= i <= 2
111+
if i == 1
112+
∇g[1] = x[2] * x[3] * x[4] # 1,1
113+
∇g[2] = x[1] * x[3] * x[4] # 1,2
114+
∇g[3] = x[1] * x[2] * x[4] # 1,3
115+
∇g[4] = x[1] * x[2] * x[3] # 1,4
116+
else
117+
∇g[1] = 2 * x[1] # 2,1
118+
∇g[2] = 2 * x[2] # 2,2
119+
∇g[3] = 2 * x[3] # 2,3
120+
∇g[4] = 2 * x[4] # 2,4
121+
end
122+
return
123+
end
124+
102125
function MOI.jacobian_structure(::HS071)
103126
return Tuple{Int64,Int64}[
104127
(1, 1),
@@ -112,22 +135,6 @@ function MOI.jacobian_structure(::HS071)
112135
]
113136
end
114137

115-
function MOI.hessian_lagrangian_structure(d::HS071)
116-
@assert d.enable_hessian
117-
return Tuple{Int64,Int64}[
118-
(1, 1),
119-
(2, 1),
120-
(2, 2),
121-
(3, 1),
122-
(3, 2),
123-
(3, 3),
124-
(4, 1),
125-
(4, 2),
126-
(4, 3),
127-
(4, 4),
128-
]
129-
end
130-
131138
function MOI.eval_constraint_jacobian(::HS071, J, x)
132139
# Constraint (row) 1
133140
J[1] = x[2] * x[3] * x[4] # 1,1
@@ -142,6 +149,17 @@ function MOI.eval_constraint_jacobian(::HS071, J, x)
142149
return
143150
end
144151

152+
function MOI.eval_constraint_jacobian_product(d::HS071, y, x, w)
153+
y .= zero(eltype(y))
154+
indices = MOI.jacobian_structure(d)
155+
J = zeros(length(indices))
156+
MOI.eval_constraint_jacobian(d, J, x)
157+
for ((i, j), val) in zip(indices, J)
158+
y[i] += val * w[j]
159+
end
160+
return
161+
end
162+
145163
function MOI.eval_constraint_jacobian_transpose_product(::HS071, y, x, w)
146164
y[1] = (x[2] * x[3] * x[4]) * w[1] + (2 * x[1]) * w[2]
147165
y[2] = (x[1] * x[3] * x[4]) * w[1] + (2 * x[2]) * w[2]
@@ -150,6 +168,64 @@ function MOI.eval_constraint_jacobian_transpose_product(::HS071, y, x, w)
150168
return
151169
end
152170

171+
function MOI.hessian_objective_structure(d::HS071)
172+
return [(1, 1), (2, 1), (3, 1), (4, 1), (4, 2), (4, 3)]
173+
end
174+
175+
function MOI.eval_hessian_objective(d::HS071, H, x)
176+
@assert d.enable_hessian
177+
H[1] = 2 * x[4] # 1,1
178+
H[2] = x[4] # 2,1
179+
H[3] = x[4] # 3,1
180+
H[4] = 2 * x[1] + x[2] + x[3] # 4,1
181+
H[5] = x[1] # 4,2
182+
H[6] = x[1] # 4,3
183+
return
184+
end
185+
186+
function MOI.hessian_constraint_structure(d::HS071, i::Int)
187+
@assert 1 <= i <= 2
188+
if i == 1
189+
return [(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3)]
190+
else
191+
return [(1, 1), (2, 2), (3, 3), (4, 4)]
192+
end
193+
end
194+
195+
function MOI.eval_hessian_constraint(d::HS071, H, x, i)
196+
@assert d.enable_hessian
197+
if i == 1
198+
H[1] = x[3] * x[4] # 2,1
199+
H[2] = x[2] * x[4] # 3,1
200+
H[3] = x[1] * x[4] # 3,2
201+
H[4] = x[2] * x[3] # 4,1
202+
H[5] = x[1] * x[3] # 4,2
203+
H[6] = x[1] * x[2] # 4,3
204+
else
205+
H[1] = 2.0 # 1,1
206+
H[2] = 2.0 # 2,2
207+
H[3] = 2.0 # 3,3
208+
H[4] = 2.0 # 4,4
209+
end
210+
return
211+
end
212+
213+
function MOI.hessian_lagrangian_structure(d::HS071)
214+
@assert d.enable_hessian
215+
return Tuple{Int64,Int64}[
216+
(1, 1),
217+
(2, 1),
218+
(2, 2),
219+
(3, 1),
220+
(3, 2),
221+
(3, 3),
222+
(4, 1),
223+
(4, 2),
224+
(4, 3),
225+
(4, 4),
226+
]
227+
end
228+
153229
function MOI.eval_hessian_lagrangian(d::HS071, H, x, σ, μ)
154230
@assert d.enable_hessian
155231
# Again, only lower left triangle
@@ -175,7 +251,7 @@ function MOI.eval_hessian_lagrangian(d::HS071, H, x, σ, μ)
175251
H[1] += μ[2] * 2 # 1,1
176252
H[3] += μ[2] * 2 # 2,2
177253
H[6] += μ[2] * 2 # 3,3
178-
H[10] += μ[2] * 2
254+
H[10] += μ[2] * 2 # 4,4
179255
return
180256
end
181257

0 commit comments

Comments
 (0)