@@ -53,6 +53,34 @@ function test_objective_quadratic_univariate()
53
53
return
54
54
end
55
55
56
+ function test_objective_and_constraints_quadratic_univariate ()
57
+ x = MOI. VariableIndex (1 )
58
+ model = Nonlinear. Model ()
59
+ Nonlinear. set_objective (model, :($ x^ 2 + 1 ))
60
+ Nonlinear. add_constraint (model, :($ x^ 2 ), MOI. LessThan (2.0 ))
61
+ evaluator = Nonlinear. Evaluator (model, Nonlinear. SparseReverseMode (), [x])
62
+ MOI. initialize (evaluator, [:Grad , :Jac , :Hess ])
63
+ @test MOI. eval_objective (evaluator, [1.2 ]) == 1.2 ^ 2 + 1
64
+ g = [NaN ]
65
+ MOI. eval_objective_gradient (evaluator, g, [1.2 ])
66
+ @test g == [2.4 ]
67
+ @test MOI. hessian_lagrangian_structure (evaluator) == [(1 , 1 ), (1 , 1 )]
68
+ H = [NaN , NaN ]
69
+ MOI. eval_hessian_lagrangian (evaluator, H, [1.2 ], 1.5 , Float64[1.3 ])
70
+ @test H == [1.5 , 1.3 ] .* [2.0 , 2.0 ]
71
+ Hp = [NaN ]
72
+ MOI. eval_hessian_lagrangian_product (
73
+ evaluator,
74
+ Hp,
75
+ [1.2 ],
76
+ [1.2 ],
77
+ 1.5 ,
78
+ Float64[1.3 ],
79
+ )
80
+ @test Hp == [1.5 * 2.0 * 1.2 + 1.3 * 2.0 * 1.2 ]
81
+ return
82
+ end
83
+
56
84
function test_objective_quadratic_multivariate ()
57
85
x = MOI. VariableIndex (1 )
58
86
y = MOI. VariableIndex (2 )
@@ -287,14 +315,13 @@ function test_hessian_sparsity_registered_function()
287
315
Nonlinear. set_objective (model, :(f ($ x, $ z) + $ y^ 2 ))
288
316
evaluator =
289
317
Nonlinear. Evaluator (model, Nonlinear. SparseReverseMode (), [x, y, z])
290
- @test_broken :Hess in MOI. features_available (evaluator)
291
- # TODO (odow): re-enable these tests when user-defined hessians are supported
292
- # MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
293
- # @test MOI.hessian_lagrangian_structure(evaluator) ==
294
- # [(1, 1), (2, 2), (3, 3), (3, 1)]
295
- # H = fill(NaN, 4)
296
- # MOI.eval_hessian_lagrangian(evaluator, H, rand(3), 1.5, Float64[])
297
- # @test H == 1.5 .* [2.0, 2.0, 2.0, 0.0]
318
+ @test :Hess in MOI. features_available (evaluator)
319
+ MOI. initialize (evaluator, [:Grad , :Jac , :Hess ])
320
+ @test MOI. hessian_lagrangian_structure (evaluator) ==
321
+ [(1 , 1 ), (2 , 2 ), (3 , 3 ), (3 , 1 )]
322
+ H = fill (NaN , 4 )
323
+ MOI. eval_hessian_lagrangian (evaluator, H, rand (3 ), 1.5 , Float64[])
324
+ @test H == 1.5 .* [2.0 , 2.0 , 2.0 , 0.0 ]
298
325
return
299
326
end
300
327
@@ -308,6 +335,7 @@ function test_hessian_sparsity_registered_rosenbrock()
308
335
return
309
336
end
310
337
function ∇²f (H, x... )
338
+ @assert size (H) == (2 , 2 )
311
339
H[1 , 1 ] = 1200 * x[1 ]^ 2 - 400 * x[2 ] + 2
312
340
H[2 , 1 ] = - 400 * x[1 ]
313
341
H[2 , 2 ] = 200.0
@@ -318,13 +346,43 @@ function test_hessian_sparsity_registered_rosenbrock()
318
346
Nonlinear. set_objective (model, :(rosenbrock ($ x, $ y)))
319
347
evaluator =
320
348
Nonlinear. Evaluator (model, Nonlinear. SparseReverseMode (), [x, y])
321
- @test_broken :Hess in MOI. features_available (evaluator)
322
- # TODO (odow): re-enable these tests when user-defined hessians are supported
323
- # MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
324
- # @test MOI.hessian_lagrangian_structure(evaluator) == [(1, 1), (2, 2), (2, 1)]
325
- # H = fill(NaN, 3)
326
- # MOI.eval_hessian_lagrangian(evaluator, H, [1.0, 1.0], 1.5, Float64[])
327
- # @test H == 1.5 .* [802, 200, -400]
349
+ @test :Hess in MOI. features_available (evaluator)
350
+ MOI. initialize (evaluator, [:Grad , :Jac , :Hess ])
351
+ @test MOI. hessian_lagrangian_structure (evaluator) ==
352
+ [(1 , 1 ), (2 , 2 ), (2 , 1 )]
353
+ H = fill (NaN , 3 )
354
+ MOI. eval_hessian_lagrangian (evaluator, H, [1.0 , 1.0 ], 1.5 , Float64[])
355
+ @test H == 1.5 .* [802.0 , 200.0 , - 400.0 ]
356
+ return
357
+ end
358
+
359
+ function test_hessian_registered_error ()
360
+ x = MOI. VariableIndex (1 )
361
+ y = MOI. VariableIndex (2 )
362
+ f (x... ) = (1 - x[1 ])^ 2 + 100 * (x[2 ] - x[1 ]^ 2 )^ 2
363
+ function ∇f (g, x... )
364
+ g[1 ] = 400 * x[1 ]^ 3 - 400 * x[1 ] * x[2 ] + 2 * x[1 ] - 2
365
+ g[2 ] = 200 * (x[2 ] - x[1 ]^ 2 )
366
+ return
367
+ end
368
+ function ∇²f (H, x... )
369
+ H[1 , 1 ] = 1200 * x[1 ]^ 2 - 400 * x[2 ] + 2
370
+ # Wrong index! Should be [2, 1]
371
+ H[1 , 2 ] = - 400 * x[1 ]
372
+ H[2 , 2 ] = 200.0
373
+ return
374
+ end
375
+ model = Nonlinear. Model ()
376
+ Nonlinear. register_operator (model, :rosenbrock , 2 , f, ∇f, ∇²f)
377
+ Nonlinear. set_objective (model, :(rosenbrock ($ x, $ y)))
378
+ evaluator =
379
+ Nonlinear. Evaluator (model, Nonlinear. SparseReverseMode (), [x, y])
380
+ MOI. initialize (evaluator, [:Grad , :Jac , :Hess ])
381
+ H = fill (NaN , 3 )
382
+ @test_throws (
383
+ ErrorException (" Unable to access upper-triangular component: (1, 2)" ),
384
+ MOI. eval_hessian_lagrangian (evaluator, H, [1.0 , 1.0 ], 1.5 , Float64[]),
385
+ )
328
386
return
329
387
end
330
388
0 commit comments