Skip to content

Commit 68707b8

Browse files
committed
add tests
1 parent 90efc8c commit 68707b8

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

test/jump_wrapper.jl

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import DiffOpt
1111
import HiGHS
1212
import Ipopt
1313
import SCS
14+
import LinearAlgebra
1415
import MathOptInterface as MOI
1516

1617
const ATOL = 1e-3
@@ -337,6 +338,98 @@ function test_jump_api()
337338
return
338339
end
339340

341+
function test_forward_wrappers_non_parametric()
342+
# Tests set_forward_objective_function and set_forward_constraint_function
343+
# overloads on a non-parametric model.
344+
#
345+
# min x s.t. x + y == 1, x >= 0, y >= 0
346+
# Solution: x=0, y=1
347+
# Perturb constraint RHS: x + y + ϵ == 1
348+
# Sensitivity should be dy/dϵ = -1
349+
# since the slack goes to y and x is at its lower bound (active).
350+
model = JuMP.direct_model(DiffOpt.diff_optimizer(HiGHS.Optimizer))
351+
set_silent(model)
352+
@variable(model, x >= 0)
353+
@variable(model, y >= 0)
354+
@constraint(model, c1, x + y == 1)
355+
@objective(model, Min, 1.0 * x)
356+
optimize!(model)
357+
@test value(x) 0.0 atol = ATOL
358+
@test value(y) 1.0 atol = ATOL
359+
360+
DiffOpt.set_forward_objective_function(model, 0.0)
361+
DiffOpt.set_forward_constraint_function(model, c1, 1.0)
362+
DiffOpt.forward_differentiate!(model)
363+
dy = DiffOpt.get_forward_variable(model, y)
364+
@test dy -1.0 atol = ATOL
365+
366+
DiffOpt.empty_input_sensitivities!(model)
367+
DiffOpt.set_forward_constraint_function(model, c1, 0.0 * x + 1.0)
368+
DiffOpt.forward_differentiate!(model)
369+
dy2 = DiffOpt.get_forward_variable(model, y)
370+
@test dy2 dy atol = ATOL
371+
return
372+
end
373+
374+
function test_forward_vector_constraint_wrappers()
375+
# Tests set_forward_constraint_function overloads for vector constraints
376+
# using conic_diff_model (direct_model + diff_optimizer bridges differently).
377+
model = DiffOpt.conic_diff_model(SCS.Optimizer)
378+
set_silent(model)
379+
@variable(model, x)
380+
@variable(model, y)
381+
@constraint(model, c_eq, x + y == 1)
382+
@constraint(model, c_nn, [1.0 * y, 1.0 * x] in MOI.Nonnegatives(2))
383+
@objective(model, Min, 1.0 * x)
384+
optimize!(model)
385+
@test value(x) 0.0 atol = ATOL
386+
@test value(y) 1.0 atol = ATOL
387+
388+
DiffOpt.set_forward_constraint_function(model, c_nn, [0.0, 0.0])
389+
DiffOpt.set_forward_constraint_function(model, c_eq, 1.0)
390+
DiffOpt.forward_differentiate!(model)
391+
dy = DiffOpt.get_forward_variable(model, y)
392+
@test dy -1.0 atol = ATOL
393+
394+
DiffOpt.empty_input_sensitivities!(model)
395+
DiffOpt.set_forward_constraint_function(model, c_nn, [0.0 * x, 0.0 * x])
396+
DiffOpt.set_forward_constraint_function(model, c_eq, 1.0)
397+
DiffOpt.forward_differentiate!(model)
398+
dy2 = DiffOpt.get_forward_variable(model, y)
399+
@test dy2 dy atol = ATOL
400+
return
401+
end
402+
403+
function test_forward_psd_matrix_wrapper()
404+
# Tests set_forward_constraint_function with AbstractMatrix{<:AbstractJuMPScalar}
405+
# for PSD cone constraints. Uses a non-parametric model since
406+
# ForwardConstraintFunction is blocked on parametric models.
407+
model = Model(() -> DiffOpt.diff_optimizer(SCS.Optimizer))
408+
set_silent(model)
409+
@variable(model, x)
410+
@objective(model, Min, -x)
411+
@constraint(
412+
model,
413+
con,
414+
LinearAlgebra.Symmetric([1.0-x 0.0; 0.0 x]) in PSDCone(),
415+
)
416+
optimize!(model)
417+
@test value(x) 1.0 atol = ATOL
418+
419+
perturbation = [1.0+0.0*x 0.0*x; 0.0*x 0.0*x]
420+
DiffOpt.set_forward_constraint_function(model, con, perturbation)
421+
DiffOpt.forward_differentiate!(model)
422+
@test DiffOpt.get_forward_variable(model, x) 1.0 atol = ATOL
423+
424+
bad = [0.0*x 1.0*x; 0.0*x 0.0*x]
425+
@test_throws ErrorException DiffOpt.set_forward_constraint_function(
426+
model,
427+
con,
428+
bad,
429+
)
430+
return
431+
end
432+
340433
end # module
341434

342435
TestJuMPWrapper.runtests()

0 commit comments

Comments
 (0)