@@ -21,10 +21,10 @@ fulfilled.
2121 the stochastic problem we want to optimize
2222* `param::SDDPparameters`:
2323 the parameters of the SDDP algorithm
24- * `display ::Int64`:
24+ * `verbose ::Int64`:
2525 Default is `0`
2626 If non null, display progression in terminal every
27- `n` iterations, where `n` is number specified by display.
27+ `n` iterations, where `n` is the number specified by display.
2828
2929# Returns
3030* `V::Array{PolyhedralFunction}`:
@@ -36,20 +36,20 @@ fulfilled.
3636 number of times the solver has been called
3737
3838"""
39- function solve_SDDP (model:: SPModel , param:: SDDPparameters , display = 0 :: Int64 )
39+ function solve_SDDP (model:: SPModel , param:: SDDPparameters , verbose = 0 :: Int64 )
4040 # initialize value functions:
4141 V, problems = initialize_value_functions (model, param)
42- (display > 0 ) && println (" Initial value function loaded into memory." )
43- # Run SDDP upon example :
44- sddp_stats = run_SDDP! (model, param, V, problems, display )
42+ (verbose > 0 ) && println (" Initial value function loaded into memory." )
43+ # Run SDDP:
44+ sddp_stats = run_SDDP! (model, param, V, problems, verbose )
4545 return V, problems, sddp_stats
4646end
4747
4848
49- function solve_SDDP (model:: SPModel , param:: SDDPparameters , V:: Vector{PolyhedralFunction} , display = 0 :: Int64 )
49+ function solve_SDDP (model:: SPModel , param:: SDDPparameters , V:: Vector{PolyhedralFunction} , verbose = 0 :: Int64 )
5050 # First step: process value functions if hotstart is called
5151 problems = hotstart_SDDP (model, param, V)
52- sddp_stats = run_SDDP! (model, param, V, problems, display )
52+ sddp_stats = run_SDDP! (model, param, V, problems, verbose )
5353 return V, problems, sddp_stats
5454end
5555
@@ -59,15 +59,15 @@ function run_SDDP!(model::SPModel,
5959 param:: SDDPparameters ,
6060 V:: Vector{PolyhedralFunction} ,
6161 problems:: Vector{JuMP.Model} ,
62- display = 0 :: Int64 )
62+ verbose = 0 :: Int64 )
6363
6464 # Initialization of the counter
6565 stats = SDDPStat (0 , [], [], [], 0 )
6666
67- if display > 0
68- println (" Initialize cuts" )
69- end
67+ (verbose > 0 ) && println (" Initialize cuts" )
7068
69+ # If computation of upper-bound is needed, a set of scenarios is built
70+ # to keep always the same realization for upper bound estimation:
7171 if param. compute_upper_bound > 0
7272 upperbound_scenarios = simulate_scenarios (model. noises, param. monteCarloSize)
7373 end
@@ -77,22 +77,23 @@ function run_SDDP!(model::SPModel,
7777 stopping_test:: Bool = false
7878 iteration_count:: Int64 = 0
7979
80+ # Launch execution of forward and backward passes:
8081 while (iteration_count < param. maxItNumber) & (~ stopping_test)
81-
8282 # Time execution of current pass:
8383 tic ()
8484
85- # Build given number of scenarios according to distribution
85+ # Draw a set of scenarios according to the probability
8686 # law specified in model.noises:
8787 noise_scenarios = simulate_scenarios (model. noises, param. forwardPassNumber)
8888
89+ # ###################
8990 # Forward pass
9091 _, stockTrajectories,_,callsolver_forward = forward_simulations (model,
9192 param,
9293 problems,
9394 noise_scenarios)
9495
95-
96+ # ###################
9697 # Backward pass
9798 callsolver_backward = backward_pass! (model,
9899 param,
@@ -101,24 +102,30 @@ function run_SDDP!(model::SPModel,
101102 stockTrajectories,
102103 model. noises)
103104
104- # Update the number of call
105+ # Update the number of solver call
105106 stats. ncallsolver += callsolver_forward + callsolver_backward
106-
107107 iteration_count += 1
108108 stats. niterations += 1
109109
110+ # ###################
111+ # If specified, prune cuts:
110112 if (param. compute_cuts_pruning > 0 ) && (iteration_count% param. compute_cuts_pruning== 0 )
111- (display > 0 ) && println (" Prune cuts ..." )
113+ (verbose > 0 ) && println (" Prune cuts ..." )
112114 remove_redundant_cuts! (V)
113115 prune_cuts! (model, param, V)
114116 problems = hotstart_SDDP (model, param, V)
115117 end
118+
119+ # Update estimation of lower bound:
116120 lwb = get_bellman_value (model, param, 1 , V[1 ], model. initialState)
117121 push! (stats. lower_bounds, lwb)
118122
123+ # ###################
124+ # If specified, compute upper-bound:
119125 if (param. compute_upper_bound > 0 ) && (iteration_count% param. compute_upper_bound== 0 )
120- (display > 0 ) && println (" Compute upper-bound with " ,
126+ (verbose > 0 ) && println (" Compute upper-bound with " ,
121127 param. monteCarloSize, " scenarios..." )
128+ # estimate upper-bound with Monte-Carlo estimation:
122129 upb, costs = estimate_upper_bound (model, param, upperbound_scenarios, problems)
123130 if param. gap > 0.
124131 stopping_test = test_stopping_criterion (lwb, upb, param. gap)
@@ -128,26 +135,21 @@ function run_SDDP!(model::SPModel,
128135 push! (stats. exectime, toq ())
129136 push! (stats. upper_bounds, upb)
130137
131- if (display > 0 ) && (iteration_count% display== 0 )
132- if upb < Inf
133- println (" Pass number " , iteration_count,
134- " \t Upper-bound: " , upb,
135- " \t Lower-bound: " , round (stats. lower_bounds[end ], 4 ),
136- " \t Time: " , round (stats. exectime[end ], 2 )," s" )
137- else
138- println (" Pass number " , iteration_count,
139- " \t Lower-bound: " , round (stats. lower_bounds[end ], 4 ),
140- " \t Time: " , round (stats. exectime[end ], 2 )," s" )
141- end
138+ if (verbose > 0 ) && (iteration_count% verbose== 0 )
139+ print (" Pass number " , iteration_count)
140+ (upb < Inf ) && print (" \t Upper-bound: " , upb)
141+ println (" \t Lower-bound: " , round (stats. lower_bounds[end ], 4 ),
142+ " \t Time: " , round (stats. exectime[end ], 2 )," s" )
142143 end
143144
144145 end
145146
146- # Estimate upper bound with a great number of simulations:
147- if (display> 0 ) && (param. compute_upper_bound != 0 )
147+ # #########
148+ # Estimate final upper bound with param.monteCarloSize simulations:
149+ if (verbose> 0 ) && (param. compute_upper_bound != 0 )
148150 V0 = get_bellman_value (model, param, 1 , V[1 ], model. initialState)
149151
150- if param. compute_upper_bound == - 1
152+ if param. compute_upper_bound == 0
151153 println (" Estimate upper-bound with Monte-Carlo ..." )
152154 upb, costs = estimate_upper_bound (model, param, V, problems)
153155 end
@@ -188,7 +190,6 @@ function estimate_upper_bound(model::SPModel, param::SDDPparameters,
188190 V:: Vector{PolyhedralFunction} ,
189191 problem:: Vector{JuMP.Model} ,
190192 n_simulation= 1000 :: Int )
191-
192193 aleas = simulate_scenarios (model. noises, n_simulation)
193194 costs, stockTrajectories, _ = forward_simulations (model, param, problem, aleas)
194195 return upper_bound (costs), costs
@@ -252,49 +253,46 @@ linear problem.
252253* `Array::JuMP.Model`:
253254"""
254255function build_models (model:: SPModel , param:: SDDPparameters )
256+ return JuMP. Model[build_model (model, param, t) for t= 1 : model. stageNumber- 1 ]
257+ end
255258
256- models = Vector {JuMP.Model} (model. stageNumber- 1 )
257-
258- for t = 1 : model. stageNumber- 1
259- m = Model (solver= param. solver)
259+ function build_model (model, param, t)
260+ m = Model (solver= param. solver)
260261
261- nx = model. dimStates
262- nu = model. dimControls
263- nw = model. dimNoises
262+ nx = model. dimStates
263+ nu = model. dimControls
264+ nw = model. dimNoises
264265
265- @variable (m, model. xlim[i][1 ] <= x[i= 1 : nx] <= model. xlim[i][2 ])
266- @variable (m, model. ulim[i][1 ] <= u[i= 1 : nu] <= model. ulim[i][2 ])
267- @variable (m, model. xlim[i][1 ] <= xf[i= 1 : nx]<= model. xlim[i][2 ])
268- @variable (m, alpha)
266+ @variable (m, model. xlim[i][1 ] <= x[i= 1 : nx] <= model. xlim[i][2 ])
267+ @variable (m, model. ulim[i][1 ] <= u[i= 1 : nu] <= model. ulim[i][2 ])
268+ @variable (m, model. xlim[i][1 ] <= xf[i= 1 : nx]<= model. xlim[i][2 ])
269+ @variable (m, alpha)
269270
270- @variable (m, w[1 : nw] == 0 )
271- m. ext[:cons ] = @constraint (m, state_constraint, x .== 0 )
271+ @variable (m, w[1 : nw] == 0 )
272+ m. ext[:cons ] = @constraint (m, state_constraint, x .== 0 )
272273
273- @constraint (m, xf .== model. dynamics (t, x, u, w))
274+ @constraint (m, xf .== model. dynamics (t, x, u, w))
274275
275- if model. equalityConstraints != nothing
276- @constraint (m, model. equalityConstraints (t, x, u, w) .== 0 )
277- end
278- if model. inequalityConstraints != nothing
279- @constraint (m, model. inequalityConstraints (t, x, u, w) .<= 0 )
280- end
276+ if model. equalityConstraints != nothing
277+ @constraint (m, model. equalityConstraints (t, x, u, w) .== 0 )
278+ end
279+ if model. inequalityConstraints != nothing
280+ @constraint (m, model. inequalityConstraints (t, x, u, w) .<= 0 )
281+ end
281282
282- if typeof (model) == LinearDynamicLinearCostSPmodel
283- @objective (m, Min, model. costFunctions (t, x, u, w) + alpha)
283+ if typeof (model) == LinearDynamicLinearCostSPmodel
284+ @objective (m, Min, model. costFunctions (t, x, u, w) + alpha)
284285
285- elseif typeof (model) == PiecewiseLinearCostSPmodel
286- @variable (m, cost)
286+ elseif typeof (model) == PiecewiseLinearCostSPmodel
287+ @variable (m, cost)
287288
288- for i in 1 : length (model. costFunctions)
289- @constraint (m, cost >= model. costFunctions[i](t, x, u, w))
290- end
291- @objective (m, Min, cost + alpha)
289+ for i in 1 : length (model. costFunctions)
290+ @constraint (m, cost >= model. costFunctions[i](t, x, u, w))
292291 end
293-
294- models[t] = m
295-
292+ @objective (m, Min, cost + alpha)
296293 end
297- return models
294+
295+ return m
298296end
299297
300298
@@ -339,13 +337,8 @@ function initialize_value_functions(model::SPModel,
339337 stockTrajectories[i, j, :] = get_random_state (model)
340338 end
341339
342-
343- callsolver = backward_pass! (model,
344- param,
345- V,
346- solverProblems,
347- stockTrajectories,
348- model. noises)
340+ callsolver = backward_pass! (model, param, V, solverProblems,
341+ stockTrajectories, model. noises)
349342
350343 return V, solverProblems
351344end
@@ -370,6 +363,7 @@ function hotstart_SDDP(model::SPModel, param::SDDPparameters, V::Vector{Polyhedr
370363
371364 solverProblems = build_models (model, param)
372365
366+ # Add corresponding cuts to each problem:
373367 for t in 1 : model. stageNumber- 2
374368 add_cuts_to_model! (model, t, solverProblems[t], V[t+ 1 ])
375369 end
0 commit comments