Skip to content

Commit

Permalink
Improve test coverage (#811)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow authored Dec 3, 2024
1 parent 0c99d6e commit 601472f
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 19 deletions.
13 changes: 2 additions & 11 deletions src/plugins/stopping_rules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,9 @@ function convergence_test(

if graph.objective_sense == MOI.MIN_SENSE
return sample_mean - sample_ci <= current_bound
elseif graph.objective_sense == MOI.MAX_SENSE
return current_bound <= sample_mean + sample_ci
else
# If sense is none of the above for some awkward reason, return to
# previous criteria
return sample_mean - sample_ci <=
current_bound <=
sample_mean + sample_ci
@assert graph.objective_sense == MOI.MAX_SENSE
return current_bound <= sample_mean + sample_ci
end
end

Expand Down Expand Up @@ -281,10 +276,6 @@ mutable struct SimulationStoppingRule{F} <: AbstractStoppingRule
bound_tol::Float64
end

function _get_state_variable_value(key)
return sp -> JuMP.value(JuMP.variable_by_name(sp, "$(key)_out"))
end

"""
SimulationStoppingRule(;
sampling_scheme::AbstractSamplingScheme = SDDP.InSampleMonteCarlo(),
Expand Down
9 changes: 4 additions & 5 deletions src/visualization/spaghetti_plot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,14 @@ function save(p::SpaghettiPlot, args...; kwargs...)
return plot(p, args...; kwargs...)
end

function launch_file(filename)
function launch_file(filename, fn = run)
if Sys.iswindows()
run(`$(ENV["COMSPEC"]) /c start $(filename)`)
return fn(`$(ENV["COMSPEC"]) /c start $(filename)`)
elseif Sys.isapple()
run(`open $(filename)`)
return fn(`open $(filename)`)
elseif Sys.islinux() || Sys.isbsd()
run(`xdg-open $(filename)`)
return fn(`xdg-open $(filename)`)
else
error("Unable to show plot. Try opening the file $(filename) manually.")
end
return
end
1 change: 1 addition & 0 deletions test/binary_expansion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function test_Binary_Expansion()
@test bincontract([0, 1, 0], 0.1) 0.2
@test bincontract([1, 1, 0], 0.1) 0.3
@test bincontract([1, 0, 1], 0.1) 0.5
return
end

end # module
Expand Down
11 changes: 10 additions & 1 deletion test/plugins/bellman_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,16 +362,25 @@ function test_biobjective_cut_selection()
)
end
end
SDDP.train_biobjective(
ret = SDDP.train_biobjective(
model;
solution_limit = 10,
iteration_limit = 10,
print_level = 0,
)
@test ret isa Dict{Float64,Float64}
n_cuts = count(model[1].bellman_function.global_theta.cuts) do cut
return cut.constraint_ref !== nothing
end
@test n_cuts < 100
ret = SDDP.train_biobjective(
model;
solution_limit = 10,
iteration_limit = 10,
print_level = 0,
include_timing = true,
)
@test ret isa Dict{Float64,Tuple{Float64,Float64}}
return
end

Expand Down
35 changes: 35 additions & 0 deletions test/plugins/parallel_schemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,41 @@ function test_Asynchronous_optimizer()
a = SDDP.Asynchronous(HiGHS.Optimizer)
a.init_callback(model)
@test solver_name(model[2].subproblem) == "HiGHS"
model = SDDP.LinearPolicyGraph(;
stages = 3,
lower_bound = 0.0,
direct_mode = true,
optimizer = HiGHS.Optimizer,
) do sp, stage
@variable(sp, 0 <= x <= 100, SDDP.State, initial_value = 0)
@stageobjective(sp, x.in)
end
scheme = SDDP.Asynchronous()
@test_throws(
ErrorException(
"Cannot use asynchronous solver with optimizers in direct mode.",
),
scheme.init_callback(model),
)
@test_throws(
ErrorException(
"Cannot use asynchronous solver with optimizers in direct mode.",
),
SDDP._uninitialize_solver(model; throw_error = true),
)
model = SDDP.LinearPolicyGraph(; stages = 3, lower_bound = 0.0) do sp, stage
@variable(sp, 0 <= x <= 100, SDDP.State, initial_value = 0)
@stageobjective(sp, x.in)
end
scheme = SDDP.Asynchronous()
@test_throws(
ErrorException(
"You must supply an optimizer for the policy graph, either by passing\n" *
"one to the `optimizer` keyword argument to `PolicyGraph`, or by\n" *
"using `JuMP.set_optimizer(model, optimizer)`.\n",
),
scheme.init_callback(model),
)
return
end

Expand Down
21 changes: 21 additions & 0 deletions test/plugins/stopping_rules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ function test_Statistical()
[SDDP.Log(1, 12.0, 9.0, 1.0, 1, 1, " ", false)],
rule,
)
rule = SDDP.Statistical(; num_replications = 20, iteration_period = 2)
@test !SDDP.convergence_test(
model,
[SDDP.Log(1, 6.0, 9.0, 1.0, 1, 1, " ", false)],
rule,
)
return
end

Expand Down Expand Up @@ -194,6 +200,17 @@ function test_BoundStalling()
],
rule,
)
rule = SDDP.BoundStalling(5, 1.0)
@test !SDDP.convergence_test(
graph,
[
SDDP.Log(1, 0.0, 0.0, 1.0, 1, 1, " ", false),
SDDP.Log(2, 0.0, 0.0, 1.0, 1, 1, " ", false),
SDDP.Log(3, 0.0, 0.0, 1.0, 1, 1, " ", false),
SDDP.Log(4, 0.0, 0.0, 1.0, 1, 1, " ", false),
],
rule,
)
return
end

Expand Down Expand Up @@ -276,6 +293,10 @@ function test_SimulationStoppingRule()
@test !SDDP.convergence_test(graph, log[1:10], rule)
@test !SDDP.convergence_test(graph, log[1:19], rule)
@test SDDP.convergence_test(graph, log[1:20], rule)
rule = SDDP.SimulationStoppingRule(; period = 1)
rule.last_iteration = 20
@test rule.period == 1
@test !SDDP.convergence_test(graph, log, rule)
return
end

Expand Down
76 changes: 74 additions & 2 deletions test/user_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -453,13 +453,31 @@ function test_numerical_stability_report()
lower_bound = -1e10,
direct_mode = false,
) do subproblem, t
@variable(subproblem, x >= -1e7, SDDP.State, initial_value = 1e-5)
@variable(subproblem, x >= -1e-7, SDDP.State, initial_value = 1e-5)
@variable(subproblem, 1 <= y <= 5, Int) # Note: this is just to test range fallback
@constraint(subproblem, 1e9 * x.out >= 1e-6 * x.in + 1e-8)
@constraint(subproblem, 1e-8 <= x.in + y <= 10)
@constraint(subproblem, [x.in, x.out, y] in MOI.ExponentialCone())
@constraint(subproblem, 1e9 * x.out >= 1e-6 * x.in + 0)
@stageobjective(subproblem, 1e9 * x.out)
end
mktempdir() do dir
filename = joinpath(dir, "log.stdout")
open(filename, "w") do io
redirect_stdout(io) do
@test SDDP.numerical_stability_report(model) === nothing
return
end
return
end
contents = read(filename, String)
@test occursin("WARNING", contents)
@test occursin("numerical stability report", contents)
return
end
report = sprint(SDDP.numerical_stability_report, model)
@test occursin("WARNING", report)
@test occursin("[1e-07, 1e+10]", report)
@test occursin("[1e-08, 1e+01]", report)
report_2 =
sprint(io -> SDDP.numerical_stability_report(io, model; by_node = true))
@test occursin("numerical stability report for node: 1", report_2)
Expand Down Expand Up @@ -518,6 +536,30 @@ function test_objective_state()
return
end

function test_objective_state_two()
model =
SDDP.LinearPolicyGraph(; stages = 2, lower_bound = 0) do subproblem, t
@variable(subproblem, x, SDDP.State, initial_value = 0)
SDDP.add_objective_state(
subproblem;
initial_value = (1.5, 0.0),
lower_bound = (0.75, 0.0),
upper_bound = (2.25, 0.0),
lipschitz = (100.0, 100.0),
) do y, ω
return (y + ω, y)
end
SDDP.parameterize(subproblem, [1, 2]) do ω
ret = SDDP.objective_state(subproblem)
@test ret isa Tuple{Float64,Float64}
@stageobjective(subproblem, ret[1] * x.out)
return
end
end
SDDP.parameterize(model[1], 2)
return
end

function test_belief_updater()
graph = SDDP.LinearGraph(2)
SDDP.add_edge(graph, 2 => 1, 0.9)
Expand Down Expand Up @@ -839,6 +881,36 @@ function test_policy_graph_sense_error()
return
end

function test_print_problem_statistics()
graph = SDDP.Graph(0)
for i in 1:4
SDDP.add_node(graph, i)
end
SDDP.add_edge(graph, 0 => 1, 1.0)
SDDP.add_edge(graph, 0 => 4, 0.0)
SDDP.add_edge(graph, 1 => 2, 0.2)
SDDP.add_edge(graph, 1 => 3, 0.3)
SDDP.add_edge(graph, 1 => 4, 0.5)
SDDP.add_edge(graph, 2 => 3, 0.5)
SDDP.add_edge(graph, 2 => 4, 0.5)
SDDP.add_edge(graph, 3 => 4, 1.0)
graph
model = SDDP.PolicyGraph(graph; lower_bound = 0.0) do sp, t
@variable(sp, x, SDDP.State, initial_value = 1.0)
@constraint(sp, x.in == x.out)
end
contents = sprint(
SDDP.print_problem_statistics,
model,
false,
nothing,
nothing,
nothing,
)
@test occursin("scenarios : 4.00000e+00", contents)
return
end

end # module

TestUserInterface.runtests()
1 change: 1 addition & 0 deletions test/visualization/visualization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function test_SpaghettiPlot()
@test read("test.html", String) == read(control, String)
end
rm("test.html")
@test SDDP.launch_file("test.html", identity) isa Cmd
return
end

Expand Down

0 comments on commit 601472f

Please sign in to comment.