Skip to content

Commit 8d8adda

Browse files
authored
Merge pull request #99 from JuliaOpt/refactoring
Refactoring
2 parents 678bcb0 + ee6f512 commit 8d8adda

File tree

4 files changed

+44
-70
lines changed

4 files changed

+44
-70
lines changed

src/SDDPoptimize.jl

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,22 @@ fulfilled.
3434
each value function
3535
* `count_callsolver::Int64`:
3636
number of times the solver has been called
37-
37+
3838
"""
3939
function solve_SDDP(model::SPModel, param::SDDPparameters, display=0::Int64)
4040
# initialize value functions:
4141
V, problems = initialize_value_functions(model, param)
4242
# Run SDDP upon example:
43-
count_callsolver = run_SDDP!(model, param, V, problems, display)
44-
return V, problems, count_callsolver
43+
sddp_stats = run_SDDP!(model, param, V, problems, display)
44+
return V, problems, sddp_stats
4545
end
4646

4747

4848
function solve_SDDP(model::SPModel, param::SDDPparameters, V::Vector{PolyhedralFunction}, display=0::Int64)
4949
# First step: process value functions if hotstart is called
5050
problems = hotstart_SDDP(model, param, V)
51-
count_callsolver = run_SDDP!(model, param, V, problems, display)
52-
return V, problems, count_callsolver
51+
sddp_stats = run_SDDP!(model, param, V, problems, display)
52+
return V, problems, sddp_stats
5353
end
5454

5555

@@ -61,7 +61,7 @@ function run_SDDP!(model::SPModel,
6161
display=0::Int64)
6262

6363
#Initialization of the counter
64-
count_callsolver::Int = 0
64+
stats = SDDPStat(0, [], [], [], 0)
6565

6666
if display > 0
6767
println("Initialize cuts")
@@ -77,10 +77,9 @@ function run_SDDP!(model::SPModel,
7777
iteration_count::Int64 = 0
7878

7979
while (iteration_count < param.maxItNumber) & (~stopping_test)
80+
8081
# Time execution of current pass:
81-
if display > 0
82-
tic()
83-
end
82+
tic()
8483

8584
# Build given number of scenarios according to distribution
8685
# law specified in model.noises:
@@ -103,32 +102,37 @@ function run_SDDP!(model::SPModel,
103102
false)
104103

105104
#Update the number of call
106-
count_callsolver += callsolver_forward + callsolver_backward
105+
stats.ncallsolver += callsolver_forward + callsolver_backward
107106

108107
iteration_count += 1
108+
stats.niterations += 1
109109

110110
if (param.compute_cuts_pruning > 0) && (iteration_count%param.compute_cuts_pruning==0)
111111
(display > 0) && println("Prune cuts ...")
112112
remove_redundant_cuts!(V)
113113
prune_cuts!(model, param, V)
114114
problems = hotstart_SDDP(model, param, V)
115115
end
116+
lwb = get_bellman_value(model, param, 1, V[1], model.initialState)
117+
push!(stats.lower_bounds, lwb)
116118

117119
if (param.compute_upper_bound > 0) && (iteration_count%param.compute_upper_bound==0)
118120
(display > 0) && println("Compute upper-bound with ",
119121
param.monteCarloSize, " scenarios...")
120122
upb, costs = estimate_upper_bound(model, param, upperbound_scenarios, problems)
121123
if param.gap > 0.
122-
lwb = get_bellman_value(model, param, 1, V[1], model.initialState)
123124
stopping_test = test_stopping_criterion(lwb, upb, param.gap)
124125
end
125126
end
126127

128+
push!(stats.exectime, toq())
129+
push!(stats.upper_bounds, upb)
130+
127131
if (display > 0) && (iteration_count%display==0)
128132
println("Pass number ", iteration_count,
129133
"\tUpper-bound: ", upb,
130-
"\tLower-bound: ", round(get_bellman_value(model, param, 1, V[1], model.initialState),4),
131-
"\tTime: ", round(toq(),2),"s")
134+
"\tLower-bound: ", round(stats.lower_bounds[end], 4),
135+
"\tTime: ", round(stats.exectime[end], 2),"s")
132136
end
133137

134138
end
@@ -149,7 +153,7 @@ function run_SDDP!(model::SPModel,
149153
round(mean(costs),4), " +/- ", round(1.96*std(costs)/sqrt(length(costs)),4))
150154
end
151155

152-
return count_callsolver
156+
return stats
153157
end
154158

155159

@@ -180,15 +184,11 @@ function estimate_upper_bound(model::SPModel, param::SDDPparameters,
180184
n_simulation=1000::Int)
181185

182186
aleas = simulate_scenarios(model.noises, n_simulation)
183-
184-
callsolver::Int = 0
185-
costs, stockTrajectories, _ = forward_simulations(model,
186-
param,
187-
problem,
188-
aleas)
189-
187+
costs, stockTrajectories, _ = forward_simulations(model, param, problem, aleas)
190188
return upper_bound(costs), costs
191189
end
190+
191+
192192
function estimate_upper_bound(model::SPModel, param::SDDPparameters,
193193
aleas::Array{Float64, 3},
194194
problem::Vector{JuMP.Model})
@@ -199,13 +199,7 @@ end
199199

200200
"""Build a collection of cuts initialized at 0"""
201201
function get_null_value_functions_array(model::SPModel)
202-
203-
V = Vector{PolyhedralFunction}(model.stageNumber)
204-
for t = 1:model.stageNumber
205-
V[t] = PolyhedralFunction(zeros(1), zeros(1, model.dimStates), 1)
206-
end
207-
208-
return V
202+
return [PolyhedralFunction(zeros(1), zeros(1, model.dimStates), 1) for i in 1:model.stageNumber]
209203
end
210204

211205

@@ -298,7 +292,6 @@ function build_models(model::SPModel, param::SDDPparameters)
298292
end
299293

300294

301-
302295
"""
303296
Initialize value functions along a given trajectory
304297
@@ -461,7 +454,8 @@ Compute optimal control at point xt and time t.
461454
# Return
462455
`Vector{Float64}`: optimal control at time t
463456
"""
464-
function get_control(model::SPModel, param::SDDPparameters, lpproblem::Vector{JuMP.Model}, t::Int, xt::Vector{Float64}, xi::Vector{Float64})
457+
function get_control(model::SPModel, param::SDDPparameters, lpproblem::Vector{JuMP.Model},
458+
t::Int, xt::Vector{Float64}, xi::Vector{Float64})
465459
return solve_one_step_one_alea(model, param, lpproblem[t], t, xt, xi)[2].optimal_control
466460
end
467461

@@ -565,3 +559,4 @@ function is_cut_relevant(model::SPModel, k::Int, Vt::PolyhedralFunction, solver;
565559
sol = getobjectivevalue(m)
566560
return sol < epsilon
567561
end
562+

src/compare.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Compare different sets of parameters to solve an instance of SDDP
1212
1313
# Description
1414
Take a collection of SDDP parameters and compare the time of execution,
15-
the memory used, an estimation of the gap to optimality and the number
15+
the memory used, an estimation of the gap to optimality and the number
1616
of calls to the solver
1717
1818
# Arguments
@@ -24,7 +24,7 @@ of calls to the solver
2424
Set of scenarios used to calculate costs
2525
* `seeds::Int`
2626
The random number generator seeds
27-
27+
2828
# Output
2929
* `Display in the terminal`
3030
Print information in the terminal
@@ -44,21 +44,21 @@ function benchmark_parameters(model,
4444

4545
srand(seeds)
4646

47-
(V, pbs, callsolver), t1, m1 = @timed solve_SDDP(model, sddpparams, 0)
47+
(V, pbs, sddpstats), t1, m1 = @timed solve_SDDP(model, sddpparams, 0)
4848
V0, t2, m2 = @timed get_bellman_value(model, sddpparams, 1, V[1], model.initialState)
4949
(upb, costs), t3, m3 = @timed estimate_upper_bound(model, sddpparams, scenarios, pbs)
5050

5151
solvingtime = t1
5252
simulationtime = t2+t3
5353
solvingmemory = m1
5454
simulationmemory = m2+m3
55-
55+
5656
print("Instance \t")
5757
print("Solving time = ",round(solvingtime,4),"\t")
5858
print("Solving memory = ", solvingmemory,"\t")
5959
print("Simulation time = ",round(simulationtime,4),"\t")
6060
print("Simulation memory = ", simulationmemory,"\t")
6161
print("Gap < ", round(100*(upb-V0)/V0),"% with prob 97.5%\t")
62-
println("number external solver call = ", callsolver)
62+
println("number external solver call = ", sddpstats.ncallsolver)
6363
end
6464
end

src/noises.jl

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -129,40 +129,6 @@ function sampling(law::Vector{NoiseLaw}, t::Int64)
129129
end
130130

131131

132-
"""
133-
DEPRECATED
134-
Simulate n scenarios according to a given NoiseLaw
135-
136-
Parameters:
137-
- law::Vector{NoiseLaw}
138-
Vector of discrete independent random variables
139-
- n::Int
140-
number of simulations to compute
141-
142-
Returns :
143-
- scenarios Array(Float64,n,T)
144-
an Array of scenarios, scenarios[i,:] being the ith noise scenario
145-
"""
146-
function generate_scenarios(laws::Vector{NoiseLaw}, n::Int64)
147-
warn("deprecated generate_scenarios use simulate_scenarios")
148-
if n <= 0
149-
error("negative number of simulations")
150-
end
151-
Tf = length(laws)
152-
scenarios = Array{Vector{Float64}}(n,Tf)
153-
for i = 1:n#TODO can be parallelized
154-
scenario = []
155-
for t=1:Tf
156-
new_val = laws[t].support[:, rand(Categorical(laws[t].proba))]
157-
push!(scenario, new_val)
158-
end
159-
scenarios[i,:]=scenario
160-
end
161-
162-
return scenarios
163-
end
164-
165-
166132
"""
167133
Simulate n scenarios and return a 3D array
168134

src/objects.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,20 @@ function set_max_iterations(param::SDDPparameters, n_iter::Int)
236236
param.maxItNumber = n_iter
237237
end
238238

239-
239+
# Define an object to store evolution of solution
240+
# along iterations:
241+
type SDDPStat
242+
# Number of iterations:
243+
niterations::Int64
244+
# evolution of lower bound:
245+
lower_bounds::Vector{Float64}
246+
# evolution of upper bound:
247+
upper_bounds::Vector{Float64}
248+
# evolution of execution time:
249+
exectime::Vector{Float64}
250+
# number of calls to solver:
251+
ncallsolver::Int64
252+
end
240253

241254

242255
type NextStep

0 commit comments

Comments
 (0)