SDDP.Asynchronous for MSPFormat
bonnkleiford opened this issue · comments
Hi Oscar,
How are you? I hope everything is well.
I am exploring the SDDP.Asynchronous feature of SDDPjl for the benchmarking. I tried to follow the documentation as much as I can but I got this error message:
You must supply an optimizer for the policy graph, either by passing
one to the `optimizer` keyword argument to `PolicyGraph`, or by
using `JuMP.set_optimizer(model, optimizer)`.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] _initialize_solver(node::SDDP.Node{String}; throw_error::Bool)
@ SDDP ~/.julia/1.8/packages/SDDP/1uYYz/src/algorithm.jl:317
[3] _initialize_solver(model::SDDP.PolicyGraph{String}; throw_error::Bool)
@ SDDP ~/.julia/1.8/packages/SDDP/1uYYz/src/algorithm.jl:343
[4] master_loop(async::SDDP.Asynchronous, model::SDDP.PolicyGraph{String}, options::SDDP.Options{String})
@ SDDP ~/.julia/1.8/packages/SDDP/1uYYz/src/plugins/parallel_schemes.jl:238
[5] train(model::SDDP.PolicyGraph{String}; iteration_limit::Nothing, time_limit::Int64, print_level::Int64, log_file::String, log_frequency::Int64, log_every_seconds::Float64, run_numerical_stability_report::Bool, stopping_rules::Vector{SDDP.AbstractStoppingRule}, risk_measure::SDDP.Expectation, sampling_scheme::SDDP.InSampleMonteCarlo, cut_type::SDDP.CutType, cycle_discretization_delta::Float64, refine_at_similar_nodes::Bool, cut_deletion_minimum::Int64, backward_sampling_scheme::SDDP.CompleteSampler, dashboard::Bool, parallel_scheme::SDDP.Asynchronous, forward_pass::SDDP.DefaultForwardPass, forward_pass_resampling_probability::Nothing, add_to_existing_cuts::Bool, duality_handler::SDDP.ContinuousConicDuality, forward_pass_callback::SDDP.var"#97#104", post_iteration_callback::SDDP.var"#98#105")
@ SDDP ~/.julia/1.8/packages/SDDP/1uYYz/src/algorithm.jl:1100
[6] top-level scope
@ In[10]:1
This is what I did so far:
using SDDP, GLPK, Gurobi, DataFrames, CSV, Plots, HiGHS, NBInclude
using Distributed
Distributed.addprocs(5);
model = SDDP.MSPFormat.read_from_file("(01_7)_100")
SDDP.set_optimizer(model, Gurobi.Optimizer)
SDDP.train(model, time_limit = 10, print_level=1, log_frequency=1,
# parallel_scheme = SDDP.Asynchronous())
I have here the json files for reproduction.
Best,
I cannot open the file because I don't have enough memory on my laptop:
julia> model = SDDP.MSPFormat.read_from_file("/tmp/(01_7)_100/(01_7)_100")
A policy graph with 2500 nodes.
Node indices: 1766, ..., 306
julia> SDDP.set_optimizer(model, Gurobi.Optimizer)
ERROR: Gurobi Error 10001:
You probably need: https://odow.github.io/SDDP.jl/stable/guides/improve_computational_performance/#Initialization-hooks
SDDP.set_optimizer(model, Gurobi.Optimizer)
SDDP.train(
model;
parallel_scheme = SDDP.Asynchronous() do m::SDDP.PolicyGraph
env = Gurobi.Env()
JuMP.set_optimizer(m, () -> Gurobi.Optimizer(env))
end,
)
But a much bigger problem is that SDDP.jl is not designed for lattices with 2500 nodes because it creates a separate JuMP model for each node in the lattice. I think I need to identify stagewise independent structure in the lattice.json
and build that instead.
The asynchronous performance is probably also bad because of #599. For this problem you'll end up creating 2500 * 5 = 12,500 different Gurobi models...
This uses #653 which is very important to ensure that only 25 subproblems get built instead of 2500.
The for-loop is a temporary fix for #654.
(base) oscar@Oscars-MBP /tmp % julia --project=sddp
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.6.7 (2022-07-19)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> using Distributed
julia> Distributed.addprocs(5);
julia> @everywhere begin
import Pkg
Pkg.activate("/tmp/sddp")
end
Activating environment at `/tmp/sddp/Project.toml`
From worker 4: Activating environment at `/tmp/sddp/Project.toml`
From worker 3: Activating environment at `/tmp/sddp/Project.toml`
From worker 2: Activating environment at `/tmp/sddp/Project.toml`
From worker 6: Activating environment at `/tmp/sddp/Project.toml`
From worker 5: Activating environment at `/tmp/sddp/Project.toml`
julia> @everywhere begin
using SDDP, Gurobi
end
julia> model = SDDP.MSPFormat.read_from_file("/tmp/(01_7)_100/(01_7)_100")
A policy graph with 25 nodes.
Node indices: 24, ..., 3
julia> SDDP.set_optimizer(model, Gurobi.Optimizer)
julia> for node in values(model.nodes)
node.optimizer = Gurobi.Optimizer
end
julia> SDDP.train(
model;
iteration_limit = 10,
log_every_seconds = 0.0,
parallel_scheme = SDDP.Asynchronous(; use_master = false) do m::SDDP.PolicyGraph
env = Gurobi.Env()
SDDP.set_optimizer(model, () -> Gurobi.Optimizer(env))
end,
)
-------------------------------------------------------------------
SDDP.jl (c) Oscar Dowson and contributors, 2017-23
-------------------------------------------------------------------
problem
nodes : 25
state variables : 1
scenarios : 1.00000e+50
existing cuts : false
options
solver : Asynchronous mode with 5 workers.
risk measure : SDDP.Expectation()
sampling scheme : SDDP.InSampleMonteCarlo
subproblem structure
VariableRef : [6, 6]
AffExpr in MOI.EqualTo{Float64} : [2, 2]
VariableRef in MOI.GreaterThan{Float64} : [5, 5]
VariableRef in MOI.LessThan{Float64} : [1, 2]
numerical stability report
matrix range [1e+00, 1e+00]
objective range [1e+00, 9e+01]
bounds range [2e+02, 1e+06]
rhs range [6e+01, 2e+02]
-------------------------------------------------------------------
iteration simulation bound time (s) solves pid
-------------------------------------------------------------------
1 1.200143e+05 9.434539e+04 5.044423e+01 100 2
2 1.346048e+05 9.434539e+04 5.202458e+01 2700 5
3 1.262865e+05 9.434539e+04 5.213052e+01 2800 6
4 1.280591e+05 9.434539e+04 5.214389e+01 2900 3
5 1.309676e+05 9.434539e+04 5.215937e+01 3000 4
6 1.179271e+05 9.906205e+04 5.217376e+01 3100 2
7 1.029976e+05 1.019992e+05 5.218820e+01 3200 2
8 1.140694e+05 1.022385e+05 5.220257e+01 3300 2
9 1.132411e+05 1.022385e+05 5.221371e+01 3400 4
10 1.006086e+05 1.025582e+05 5.222394e+01 3500 2
-------------------------------------------------------------------
status : iteration_limit
total time (s) : 5.222394e+01
total solves : 3500
best bound : 1.025582e+05
simulation ci : 1.188776e+05 ± 7.084132e+03
numeric issues : 0
-------------------------------------------------------------------
The 50 second start up latency is weird. But I don't have the time to look into it. I don't expect the asynchronous implementation to perform well in your benchmarks. See #599.
Should be fixed if you use ] add SDDP#master
Should be fixed by v1.6.2
Is the library open-source yet? Without a formal spec or a bunch of examples, it's quite hard to know if I've implemented things correctly.
Why does the library need to stay private until you've written the paper/submitted a thesis? It'd be easier to iterate and fix any problems if it was open. It doesn't need to be in a perfect state to begin with.
Any update? If not, I will close this issue.
Closing for now. I opened a few issues at https://github.com/bonnkleiford/MSPLib-Library, so let's chat there.