Skip to content

Commit 1a8faea

Browse files
authored
[Nonlinear.ReverseAD] improve test coverage (#2646)
1 parent be974ee commit 1a8faea

File tree

2 files changed

+72
-23
lines changed

2 files changed

+72
-23
lines changed

src/Nonlinear/ReverseAD/graph_tools.jl

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,7 @@ function _compute_hessian_sparsity(
228228
end
229229
for k in 2:length(nodes)
230230
nod = nodes[k]
231-
if nod.type == Nonlinear.NODE_MOI_VARIABLE
232-
error(
233-
"Internal error: Invalid to compute sparsity if Nonlinear.NODE_MOI_VARIABLE " *
234-
"nodes are present.",
235-
)
236-
end
231+
@assert nod.type != Nonlinear.NODE_MOI_VARIABLE
237232
if nonlinear_wrt_output[k]
238233
continue # already seen this node one way or another
239234
elseif input_linearity[k] == CONSTANT
@@ -473,20 +468,3 @@ function _order_subexpressions(
473468
)
474469
return full_sort, individual_sorts
475470
end
476-
477-
"""
478-
_order_subexpressions(
479-
main_expression::Vector{Nonlinear.Node},
480-
subexpressions::Vector{Vector{Nonlinear.Node}},
481-
)
482-
483-
Return a `Vector{Int}` containing the topologically ordered list of
484-
subexpression-indices that need to be evaluated to compute `main_expression`.
485-
"""
486-
function _order_subexpressions(
487-
main_expression::Vector{Nonlinear.Node},
488-
subexpressions::Vector{Vector{Nonlinear.Node}},
489-
)
490-
s = _list_subexpressions(main_expression)
491-
return _topological_sort(s, subexpressions)
492-
end

test/Nonlinear/ReverseAD.jl

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,77 @@ function test_unsafe_vector_view()
12331233
return
12341234
end
12351235

1236+
function test_classify_linearity_ifelse()
1237+
x = MOI.VariableIndex(1)
1238+
y = MOI.VariableIndex(2)
1239+
model = MOI.Nonlinear.Model()
1240+
MOI.Nonlinear.set_objective(model, :(ifelse($y, $x, 1)))
1241+
evaluator = MOI.Nonlinear.Evaluator(
1242+
model,
1243+
MOI.Nonlinear.SparseReverseMode(),
1244+
[x, y],
1245+
)
1246+
MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
1247+
@test MOI.eval_objective(evaluator, [1.2, 1.0]) == 1.2
1248+
@test MOI.eval_objective(evaluator, [1.2, 0.0]) == 1.0
1249+
@test isempty(MOI.hessian_lagrangian_structure(evaluator))
1250+
return
1251+
end
1252+
1253+
function test_classify_linearity_logic()
1254+
x = MOI.VariableIndex(1)
1255+
y = MOI.VariableIndex(2)
1256+
model = MOI.Nonlinear.Model()
1257+
MOI.Nonlinear.set_objective(model, :($x && $y))
1258+
evaluator = MOI.Nonlinear.Evaluator(
1259+
model,
1260+
MOI.Nonlinear.SparseReverseMode(),
1261+
[x, y],
1262+
)
1263+
MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
1264+
@test MOI.eval_objective(evaluator, [1.0, 1.0]) == 1.0
1265+
@test MOI.eval_objective(evaluator, [0.0, 1.0]) == 0.0
1266+
@test MOI.eval_objective(evaluator, [1.0, 0.0]) == 0.0
1267+
@test MOI.eval_objective(evaluator, [0.0, 0.0]) == 0.0
1268+
@test isempty(MOI.hessian_lagrangian_structure(evaluator))
1269+
return
1270+
end
1271+
1272+
function test_hessian_sparsity_with_subexpressions()
1273+
x = MOI.VariableIndex(1)
1274+
y = MOI.VariableIndex(2)
1275+
model = MOI.Nonlinear.Model()
1276+
expr = MOI.Nonlinear.add_expression(model, :($x * $y))
1277+
expr2 = MOI.Nonlinear.add_expression(model, :($expr))
1278+
MOI.Nonlinear.set_objective(model, :(sin($expr2)))
1279+
evaluator = MOI.Nonlinear.Evaluator(
1280+
model,
1281+
MOI.Nonlinear.SparseReverseMode(),
1282+
[x, y],
1283+
)
1284+
MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
1285+
MOI.hessian_lagrangian_structure(evaluator)
1286+
return
1287+
end
1288+
1289+
function test_toposort_subexpressions()
1290+
x = MOI.VariableIndex(1)
1291+
model = MOI.Nonlinear.Model()
1292+
a = MOI.Nonlinear.add_expression(model, :($x))
1293+
b = MOI.Nonlinear.add_expression(model, :($x))
1294+
c = MOI.Nonlinear.add_expression(model, :($a + $b))
1295+
d = MOI.Nonlinear.add_expression(model, :($c + $b))
1296+
MOI.Nonlinear.add_constraint(model, :($d), MOI.LessThan(1.0))
1297+
MOI.Nonlinear.add_constraint(model, :($c), MOI.LessThan(1.0))
1298+
evaluator =
1299+
MOI.Nonlinear.Evaluator(model, MOI.Nonlinear.SparseReverseMode(), [x])
1300+
MOI.initialize(evaluator, [:Grad, :Jac, :Hess])
1301+
g = [NaN, NaN]
1302+
MOI.eval_constraint(evaluator, g, [2.0])
1303+
@test g == [6.0, 4.0]
1304+
return
1305+
end
1306+
12361307
end # module
12371308

12381309
TestReverseAD.runtests()

0 commit comments

Comments
 (0)