@@ -2386,3 +2386,161 @@ function setup_test(
23862386end
23872387
23882388version_added (:: typeof (test_vector_nonlinear_oracle_no_hessian)) = v " 1.46.0"
2389+
2390+ function test_VectorNonlinearOracle_LagrangeMultipliers_MAX_SENSE (
2391+ model:: MOI.ModelLike ,
2392+ config:: MOI.Test.Config{T} ,
2393+ ) where {T}
2394+ @requires _supports (config, MOI. optimize!)
2395+ @requires _supports (config, MOI. ConstraintDual)
2396+ @requires _supports (config, MOI. LagrangeMultiplier)
2397+ @requires MOI. supports_constraint (
2398+ model,
2399+ MOI. VectorOfVariables,
2400+ MOI. VectorNonlinearOracle{T},
2401+ )
2402+ set = MOI. VectorNonlinearOracle (;
2403+ dimension = 2 ,
2404+ l = T[typemin (T)],
2405+ u = T[1 ],
2406+ eval_f = (ret, x) -> (ret[1 ] = x[1 ]^ 2 + x[2 ]^ 2 ),
2407+ jacobian_structure = [(1 , 1 ), (1 , 2 )],
2408+ eval_jacobian = (ret, x) -> ret .= T (2 ) .* x,
2409+ hessian_lagrangian_structure = [(1 , 1 ), (2 , 2 )],
2410+ eval_hessian_lagrangian = (ret, x, u) -> ret .= T (2 ) .* u[1 ],
2411+ )
2412+ x = MOI. add_variables (model, 2 )
2413+ MOI. set (model, MOI. ObjectiveSense (), MOI. MAX_SENSE)
2414+ f = one (T) * x[1 ] + one (T) * x[2 ]
2415+ MOI. set (model, MOI. ObjectiveFunction {typeof(f)} (), f)
2416+ c = MOI. add_constraint (model, MOI. VectorOfVariables (x), set)
2417+ y = T (1 ) / sqrt (T (2 ))
2418+ CI = MOI. ConstraintIndex{MOI. VectorOfVariables,MOI. VectorNonlinearOracle{T}}
2419+ if MOI. supports (model, MOI. LagrangeMultiplierStart (), CI)
2420+ MOI. set (model, MOI. LagrangeMultiplierStart (), c, T[- y])
2421+ end
2422+ MOI. optimize! (model)
2423+ @test isapprox (MOI. get (model, MOI. VariablePrimal (), x), [y, y], config)
2424+ @test isapprox (MOI. get (model, MOI. ConstraintDual (), c), T[- 1 , - 1 ], config)
2425+ @test isapprox (MOI. get (model, MOI. LagrangeMultiplier (), c), T[- y])
2426+ # Test `set` just for code coverage
2427+ x = T[1 , 2 ]
2428+ ret = T[0 ]
2429+ set. eval_f (ret, x)
2430+ @test ret == T[5 ]
2431+ ret = T[0 , 0 ]
2432+ set. eval_jacobian (ret, x)
2433+ @test ret == T[2 , 4 ]
2434+ set. eval_hessian_lagrangian (ret, x, T[- 1 ])
2435+ @test ret == [- 2 , - 2 ]
2436+ return
2437+ end
2438+
2439+ function setup_test (
2440+ :: typeof (test_VectorNonlinearOracle_LagrangeMultipliers_MAX_SENSE),
2441+ model:: MOIU.MockOptimizer ,
2442+ config:: Config{T} ,
2443+ ) where {T}
2444+ F, S = MOI. VectorOfVariables, MOI. VectorNonlinearOracle{T}
2445+ y = T (1 ) / sqrt (T (2 ))
2446+ MOI. Utilities. set_mock_optimize! (
2447+ model,
2448+ mock -> begin
2449+ MOI. Utilities. mock_optimize! (
2450+ mock,
2451+ config. optimal_status,
2452+ T[y, y],
2453+ (F, S) => [T[- 1 , - 1 ]],
2454+ )
2455+ ci = only (MOI. get (mock, MOI. ListOfConstraintIndices {F,S} ()))
2456+ MOI. set (mock, MOI. LagrangeMultiplier (), ci, T[- y])
2457+ end ,
2458+ )
2459+ model. eval_variable_constraint_dual = false
2460+ return () -> model. eval_variable_constraint_dual = true
2461+ end
2462+
2463+ function version_added (
2464+ :: typeof (test_VectorNonlinearOracle_LagrangeMultipliers_MAX_SENSE),
2465+ )
2466+ return v " 1.48.0"
2467+ end
2468+
2469+ function test_VectorNonlinearOracle_LagrangeMultipliers_MIN_SENSE (
2470+ model:: MOI.ModelLike ,
2471+ config:: MOI.Test.Config{T} ,
2472+ ) where {T}
2473+ @requires _supports (config, MOI. optimize!)
2474+ @requires _supports (config, MOI. ConstraintDual)
2475+ @requires _supports (config, MOI. LagrangeMultiplier)
2476+ @requires MOI. supports_constraint (
2477+ model,
2478+ MOI. VectorOfVariables,
2479+ MOI. VectorNonlinearOracle{T},
2480+ )
2481+ set = MOI. VectorNonlinearOracle (;
2482+ dimension = 2 ,
2483+ l = T[- 1 ],
2484+ u = T[typemax (T)],
2485+ eval_f = (ret, x) -> (ret[1 ] = - x[1 ]^ 2 - x[2 ]^ 2 ),
2486+ jacobian_structure = [(1 , 1 ), (1 , 2 )],
2487+ eval_jacobian = (ret, x) -> ret .= - T (2 ) .* x,
2488+ hessian_lagrangian_structure = [(1 , 1 ), (2 , 2 )],
2489+ eval_hessian_lagrangian = (ret, x, u) -> ret .= - T (2 ) .* u[1 ],
2490+ )
2491+ x = MOI. add_variables (model, 2 )
2492+ MOI. set (model, MOI. ObjectiveSense (), MOI. MIN_SENSE)
2493+ f = one (T) * x[1 ] + one (T) * x[2 ]
2494+ MOI. set (model, MOI. ObjectiveFunction {typeof(f)} (), f)
2495+ c = MOI. add_constraint (model, MOI. VectorOfVariables (x), set)
2496+ y = T (1 ) / sqrt (T (2 ))
2497+ CI = MOI. ConstraintIndex{MOI. VectorOfVariables,MOI. VectorNonlinearOracle{T}}
2498+ if MOI. supports (model, MOI. LagrangeMultiplierStart (), CI)
2499+ MOI. set (model, MOI. LagrangeMultiplierStart (), c, T[y])
2500+ end
2501+ MOI. optimize! (model)
2502+ @test isapprox (MOI. get (model, MOI. VariablePrimal (), x), [- y, - y], config)
2503+ @test isapprox (MOI. get (model, MOI. ConstraintDual (), c), T[1 , 1 ], config)
2504+ @test isapprox (MOI. get (model, MOI. LagrangeMultiplier (), c), T[y])
2505+ # Test `set` just for code coverage
2506+ x = T[1 , 2 ]
2507+ ret = T[0 ]
2508+ set. eval_f (ret, x)
2509+ @test ret == T[- 5 ]
2510+ ret = T[0 , 0 ]
2511+ set. eval_jacobian (ret, x)
2512+ @test ret == T[- 2 , - 4 ]
2513+ set. eval_hessian_lagrangian (ret, x, T[- 1 ])
2514+ @test ret == [2 , 2 ]
2515+ return
2516+ end
2517+
2518+ function setup_test (
2519+ :: typeof (test_VectorNonlinearOracle_LagrangeMultipliers_MIN_SENSE),
2520+ model:: MOIU.MockOptimizer ,
2521+ config:: Config{T} ,
2522+ ) where {T}
2523+ F, S = MOI. VectorOfVariables, MOI. VectorNonlinearOracle{T}
2524+ y = T (1 ) / sqrt (T (2 ))
2525+ MOI. Utilities. set_mock_optimize! (
2526+ model,
2527+ mock -> begin
2528+ MOI. Utilities. mock_optimize! (
2529+ mock,
2530+ config. optimal_status,
2531+ T[- y, - y],
2532+ (F, S) => [T[1 , 1 ]],
2533+ )
2534+ ci = only (MOI. get (mock, MOI. ListOfConstraintIndices {F,S} ()))
2535+ MOI. set (mock, MOI. LagrangeMultiplier (), ci, T[y])
2536+ end ,
2537+ )
2538+ model. eval_variable_constraint_dual = false
2539+ return () -> model. eval_variable_constraint_dual = true
2540+ end
2541+
2542+ function version_added (
2543+ :: typeof (test_VectorNonlinearOracle_LagrangeMultipliers_MIN_SENSE),
2544+ )
2545+ return v " 1.48.0"
2546+ end
0 commit comments