Skip to content

Commit 63b4dd9

Browse files
authored
add nlp tests for FeasibilitySense (#400)
1 parent 9738f62 commit 63b4dd9

File tree

1 file changed

+134
-5
lines changed

1 file changed

+134
-5
lines changed

src/Test/nlp.jl

Lines changed: 134 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ function hs071test_template(model::MOI.ModelLike, config::TestConfig, evaluator:
114114
lb = [25.0, 40.0]
115115
ub = [Inf, 40.0]
116116

117-
hs071_data = MOI.NLPBlockData(MOI.NLPBoundsPair.(lb, ub), evaluator, true)
117+
block_data = MOI.NLPBlockData(MOI.NLPBoundsPair.(lb, ub), evaluator, true)
118118

119119
v = MOI.addvariables!(model, 4)
120120
@test MOI.get(model, MOI.NumberOfVariables()) == 4
@@ -131,11 +131,10 @@ function hs071test_template(model::MOI.ModelLike, config::TestConfig, evaluator:
131131
MOI.set!(model, MOI.VariablePrimalStart(), v[i], start[i])
132132
end
133133

134-
MOI.set!(model, MOI.NLPBlock(), hs071_data)
134+
MOI.set!(model, MOI.NLPBlock(), block_data)
135135
MOI.set!(model, MOI.ObjectiveSense(), MOI.MinSense)
136136

137137
# TODO: config.query tests
138-
139138
if config.solve
140139
MOI.optimize!(model)
141140

@@ -163,8 +162,138 @@ end
163162
hs071_test(model, config) = hs071test_template(model, config, HS071(true))
164163
hs071_no_hessian_test(model, config) = hs071test_template(model, config, HS071(false))
165164

166-
# TODO: HS071 version without hessians.
165+
# Test for FeasibilitySense.
166+
# Find x satisfying x^2 == 1.
167+
struct FeasibilitySenseEvaluator <: MOI.AbstractNLPEvaluator
168+
enable_hessian::Bool
169+
end
170+
171+
function MOI.initialize!(d::FeasibilitySenseEvaluator,
172+
requested_features::Vector{Symbol})
173+
for feat in requested_features
174+
if !(feat in MOI.features_available(d))
175+
error("Unsupported feature $feat")
176+
# TODO: implement Jac-vec and Hess-vec products
177+
# for solvers that need them
178+
end
179+
end
180+
end
181+
182+
function MOI.features_available(d::FeasibilitySenseEvaluator)
183+
if d.enable_hessian
184+
return [:Grad, :Jac, :Hess]
185+
else
186+
return [:Grad, :Jac]
187+
end
188+
end
189+
190+
191+
MOI.eval_objective(d::FeasibilitySenseEvaluator, x) = 0.0
192+
193+
function MOI.eval_constraint(d::FeasibilitySenseEvaluator, g, x)
194+
g[1] = x[1]^2
195+
end
196+
197+
function MOI.eval_objective_gradient(d::FeasibilitySenseEvaluator, grad_f, x)
198+
grad_f[1] = 0.0
199+
end
200+
201+
function MOI.jacobian_structure(d::FeasibilitySenseEvaluator)
202+
return Tuple{Int64,Int64}[(1,1)]
203+
end
204+
205+
function MOI.hessian_lagrangian_structure(d::FeasibilitySenseEvaluator)
206+
@assert d.enable_hessian
207+
return Tuple{Int64,Int64}[(1,1)]
208+
end
209+
210+
function MOI.eval_constraint_jacobian(d::FeasibilitySenseEvaluator, J, x)
211+
J[1] = 2x[1]
212+
end
213+
214+
function MOI.eval_hessian_lagrangian(d::FeasibilitySenseEvaluator, H, x, σ, μ)
215+
@assert d.enable_hessian
216+
H[1] = 2μ[1] # 1,1
217+
end
218+
219+
function feasibility_sense_test_template(model::MOI.ModelLike,
220+
config::TestConfig,
221+
set_has_objective::Bool,
222+
evaluator::FeasibilitySenseEvaluator)
223+
atol = config.atol
224+
rtol = config.rtol
225+
226+
@test MOI.supports(model, MOI.NLPBlock())
227+
@test MOI.canset(model, MOI.VariablePrimalStart(), MOI.VariableIndex)
228+
229+
MOI.empty!(model)
230+
@test MOI.isempty(model)
231+
232+
lb = [1.0]
233+
ub = [1.0]
234+
235+
block_data = MOI.NLPBlockData(MOI.NLPBoundsPair.(lb, ub), evaluator,
236+
set_has_objective)
237+
238+
x = MOI.addvariable!(model)
239+
@test MOI.get(model, MOI.NumberOfVariables()) == 1
240+
241+
# Avoid starting at zero because it's a critial point.
242+
MOI.set!(model, MOI.VariablePrimalStart(), x, 1.5)
243+
244+
MOI.set!(model, MOI.NLPBlock(), block_data)
245+
MOI.set!(model, MOI.ObjectiveSense(), MOI.FeasibilitySense)
246+
247+
# TODO: config.query tests
248+
if config.solve
249+
MOI.optimize!(model)
250+
251+
@test MOI.canget(model, MOI.TerminationStatus())
252+
@test MOI.get(model, MOI.TerminationStatus()) == MOI.Success
253+
254+
@test MOI.canget(model, MOI.ResultCount())
255+
@test MOI.get(model, MOI.ResultCount()) >= 1
256+
257+
@test MOI.canget(model, MOI.PrimalStatus())
258+
@test MOI.get(model, MOI.PrimalStatus()) == MOI.FeasiblePoint
259+
260+
@test MOI.canget(model, MOI.ObjectiveValue())
261+
@test MOI.get(model, MOI.ObjectiveValue()) 0.0 atol=atol rtol=rtol
262+
263+
@test MOI.canget(model, MOI.VariablePrimal(), MOI.VariableIndex)
264+
@test MOI.get(model, MOI.VariablePrimal(), x) 1.0 atol=atol rtol=rtol
265+
end
266+
end
267+
268+
function feasibility_sense_with_objective_and_hessian_test(model, config)
269+
feasibility_sense_test_template(model, config, true,
270+
FeasibilitySenseEvaluator(true))
271+
end
272+
273+
function feasibility_sense_with_objective_and_no_hessian_test(model, config)
274+
feasibility_sense_test_template(model, config, true,
275+
FeasibilitySenseEvaluator(false))
276+
end
277+
278+
function feasibility_sense_with_no_objective_and_with_hessian_test(model, config)
279+
feasibility_sense_test_template(model, config, false,
280+
FeasibilitySenseEvaluator(true))
281+
end
282+
283+
function feasibility_sense_with_no_objective_and_no_hessian_test(model, config)
284+
feasibility_sense_test_template(model, config, false,
285+
FeasibilitySenseEvaluator(false))
286+
end
167287

168-
const nlptests = Dict("hs071" => hs071_test, "hs071_no_hessian" => hs071_no_hessian_test)
288+
const nlptests = Dict("hs071" => hs071_test,
289+
"hs071_no_hessian" => hs071_no_hessian_test,
290+
"feasibility_sense_with_objective_and_hessian" =>
291+
feasibility_sense_with_objective_and_hessian_test,
292+
"feasibility_sense_with_objective_and_no_hessian" =>
293+
feasibility_sense_with_objective_and_no_hessian_test,
294+
"feasibility_sense_with_no_objective_and_with_hessian" =>
295+
feasibility_sense_with_no_objective_and_with_hessian_test,
296+
"feasibility_sense_with_no_objective_and_no_hessian" =>
297+
feasibility_sense_with_no_objective_and_no_hessian_test)
169298

170299
@moitestset nlp

0 commit comments

Comments
 (0)