Skip to content

Commit 53ed116

Browse files
author
Vincent Leclere
committed
[UPD] update example and adapt SDPoptimize accordingly
1 parent 9cf6b26 commit 53ed116

File tree

5 files changed

+174
-68
lines changed

5 files changed

+174
-68
lines changed

examples/stock-example.jl

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@
1010
# u_min <= u_t <= u_max
1111
# u_t choosen knowing xi_1 .. xi_t
1212
#############################################################################
13-
1413
push!(LOAD_PATH, "../src")
1514
using StochDynamicProgramming, JuMP, Clp, Distributions
15+
println("library loaded")
16+
17+
run_sddp = false
18+
run_sdp = true
1619

1720
######## Optimization parameters ########
1821
# choose the LP solver used.
1922
const SOLVER = ClpSolver()
20-
# const SOLVER = CplexSolver(CPX_PARAM_SIMDISPLAY=0)
21-
# const SOLVER = GurobiSolver()
23+
# const SOLVER = CplexSolver(CPX_PARAM_SIMDISPLAY=0) # require "using CPLEX"
2224

2325
# convergence test
2426
const MAX_ITER = 100 # maximum iteration of SDDP
@@ -40,10 +42,7 @@ const S0 = 0.5
4042
proba = 1/N_XI*ones(N_XI) # uniform probabilities
4143
xi_support = collect(linspace(XI_MIN,XI_MAX,N_XI))
4244
xi_law = NoiseLaw(xi_support, proba)
43-
xi_laws = Vector{NoiseLaw}(N_STAGES-1)
44-
for t=1:N_STAGES-1
45-
xi_laws[t] = xi_law
46-
end
45+
xi_laws = NoiseLaw[xi_law for t in 1:N_STAGES-1]
4746

4847
# Define dynamic of the stock:
4948
function dynamic(t, x, u, xi)
@@ -55,38 +54,42 @@ function cost_t(t, x, u, w)
5554
return COSTS[t] * u[1]
5655
end
5756

58-
5957
######## Setting up the SPmodel
60-
s_bounds = [(0, 1)]
61-
u_bounds = [(CONTROL_MIN, CONTROL_MAX)]
62-
spmodel = LinearDynamicLinearCostSPmodel(N_STAGES,
63-
u_bounds,
64-
[S0],
65-
cost_t,
66-
dynamic,
67-
xi_laws)
68-
69-
set_state_bounds(spmodel, s_bounds)
70-
paramSDDP = SDDPparameters(SOLVER, 10, 0, MAX_ITER) # 10 forward path, stop at MAX_ITER
58+
s_bounds = [(0, 1)]
59+
u_bounds = [(CONTROL_MIN, CONTROL_MAX)]
60+
spmodel = LinearDynamicLinearCostSPmodel(N_STAGES,u_bounds,[S0],cost_t,dynamic,xi_laws)
61+
set_state_bounds(spmodel, s_bounds)
62+
7163

7264
######### Solving the problem via SDDP
73-
V, pbs = solve_SDDP(spmodel, paramSDDP, 10) # display information every 10 iterations
74-
lb_sddp = StochDynamicProgramming.get_lower_bound(spmodel, paramSDDP, V)
75-
println("Lower bound obtained by SDDP: "*string(lb_sddp))
65+
if run_sddp
66+
paramSDDP = SDDPparameters(SOLVER, 2, 0, MAX_ITER) # 10 forward pass, stop at MAX_ITER
67+
V, pbs = solve_SDDP(spmodel, paramSDDP, 10) # display information every 10 iterations
68+
lb_sddp = StochDynamicProgramming.get_lower_bound(spmodel, paramSDDP, V)
69+
println("Lower bound obtained by SDDP: "*string(lb_sddp))
70+
end
7671

7772
######### Solving the problem via Dynamic Programming
73+
if run_sdp
74+
stateSteps = [0.01]
75+
controlSteps = [0.01]
76+
infoStruct = "HD" # noise at time t is known before taking the decision at time t
77+
78+
paramSDP = SDPparameters(spmodel, stateSteps, controlSteps, infoStruct)
79+
Vs = sdp_optimize(spmodel,paramSDP)
80+
lb_sdp = StochDynamicProgramming.get_value(spmodel,paramSDP,Vs)
81+
println("Value obtained by SDP: "*string(lb_sdp))
82+
end
7883

79-
stateSteps = [0.01]
80-
controlSteps = [0.01]
81-
infoStruct = "HD" # noise at time t is known before taking the decision at time t
82-
83-
paramSDP = SDPparameters(spmodel, stateSteps, controlSteps, infoStruct)
84-
Vs = sdp_optimize(spmodel,paramSDP)
85-
lb_sdp = StochDynamicProgramming.get_value(spmodel,paramSDP,Vs)
86-
println("Lower bound obtained by SDP: "*string(lb_sdp))
84+
######### Comparing the solution
85+
scenarios = StochDynamicProgramming.simulate_scenarios(xi_laws,2)
86+
if run_sddp
87+
costs, stocks = forward_simulations(spmodel, paramSDDP, V, pbs, scenarios)
88+
end
89+
if run_sdp
90+
costs, states, stocks =sdp_forward_simulation(spmodel,paramSDP,scenarios,Vs)
91+
end
92+
println(costs)
8793

8894

89-
######### Comparing the solution
90-
#scenarios = StochDynamicProgramming.generate_scenarios(xi_laws,1)
91-
#costs, stocks = forward_simulations(spmodel, params, V, pbs, scenarios)
9295

src/SDDPoptimize.jl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,7 @@ function run_SDDP(model::SPModel,
9494

9595
# Build given number of scenarios according to distribution
9696
# law specified in model.noises:
97-
noise_scenarios = simulate_scenarios(model.noises ,
98-
(model.stageNumber-1,
99-
param.forwardPassNumber,
100-
model.dimNoises))
97+
noise_scenarios = simulate_scenarios(model.noises, param.forwardPassNumber)
10198

10299
# Forward pass
103100
costs, stockTrajectories, _ = forward_simulations(model,

src/SDPoptimize.jl

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -117,30 +117,9 @@ function generate_grid(model::SPModel, param::SDPparameters)
117117
end
118118

119119
"""
120-
Value iteration algorithm to compute optimal value functions in
121-
the Decision Hazard (DH) as well as the Hazard Decision (HD) case
122-
123-
Parameters:
124-
- model (SPmodel)
125-
the DPSPmodel of our problem
126-
127-
- param (SDPparameters)
128-
the parameters for the SDP algorithm
129-
130-
- display (Bool)
131-
the output display or verbosity parameter
132-
133-
134-
Returns :
135-
- value_functions (Array)
136-
the vector representing the value functions as functions of the state
137-
of the system at each time step
138-
120+
Try to construct a StochDynProgModel from an SPModel
139121
"""
140-
function sdp_optimize(model::SPModel,
141-
param::SDPparameters,
142-
display=true::Bool)
143-
122+
function build_sdpmodel_from_spmodel(model::SPModel)
144123
function true_fun(t,x,u,w)
145124
return true
146125
end
@@ -150,11 +129,12 @@ function sdp_optimize(model::SPModel,
150129

151130
if isa(model,PiecewiseLinearCostSPmodel)||isa(model,LinearDynamicLinearCostSPmodel)
152131
function cons_fun(t,x,u,w)
153-
test = true
154132
for i in 1:model.dimStates
155-
test &= (x[i]>=model.xlim[i][1])&(x[i]<=model.xlim[i][2])
133+
if (x[i]<=model.xlim[i][1]) || (x[i]>=model.xlim[i][2])
134+
return false
135+
end
156136
end
157-
return test
137+
return true
158138
end
159139
if in(:finalCostFunction,fieldnames(model))
160140
SDPmodel = StochDynProgModel(model, model.finalCostFunction, cons_fun)
@@ -167,6 +147,35 @@ function sdp_optimize(model::SPModel,
167147
error("cannot build StochDynProgModel from current SPmodel. You need to implement
168148
a new StochDynProgModel constructor.")
169149
end
150+
return SDPmodel
151+
end
152+
153+
"""
154+
Value iteration algorithm to compute optimal value functions in
155+
the Decision Hazard (DH) as well as the Hazard Decision (HD) case
156+
157+
Parameters:
158+
- model (SPmodel)
159+
the DPSPmodel of our problem
160+
161+
- param (SDPparameters)
162+
the parameters for the SDP algorithm
163+
164+
- display (Bool)
165+
the output display or verbosity parameter
166+
167+
168+
Returns :
169+
- value_functions (Array)
170+
the vector representing the value functions as functions of the state
171+
of the system at each time step
172+
173+
"""
174+
function sdp_optimize(model::SPModel,
175+
param::SDPparameters,
176+
display=true::Bool)
177+
178+
SDPmodel = build_sdpmodel_from_spmodel(model::SPModel)
170179

171180
#Display start of the algorithm in DH and HD cases
172181
if (param.infoStructure == "DH")
@@ -449,6 +458,58 @@ function get_value(model::SPModel,param::SDPparameters,V::Array{Float64})
449458
return Vi[ind_x0...,1]
450459
end
451460

461+
"""
462+
Simulation of optimal trajectories given model and Bellman functions
463+
464+
Parameters:
465+
- model (SPmodel)
466+
the DPSPmodel of our problem
467+
468+
- param (SDPparameters)
469+
the parameters for the SDP algorithm
470+
471+
- scenarios (Array)
472+
the scenarios of uncertainties realizations we want to simulate on
473+
scenarios[t,k,:] is the alea at time t for scenario k
474+
475+
- value_functions (Array)
476+
the vector representing the value functions as functions of the state
477+
of the system at each time step
478+
479+
- display (Bool)
480+
the output display or verbosity parameter
481+
482+
Returns :
483+
484+
- costs (Vector{Float64})
485+
the cost of the optimal control over the scenario provided
486+
487+
- stocks (Array{Float64})
488+
the state of the controlled system at each time step
489+
490+
- controls (Array{Float64})
491+
the controls applied to the system at each time step
492+
"""
493+
function sdp_forward_simulation(model::SPModel,
494+
param::SDPparameters,
495+
scenarios::Array{Float64,3},
496+
value::Array,
497+
display=true::Bool)
498+
499+
SDPmodel = build_sdpmodel_from_spmodel(model)
500+
TF = SDPmodel.stageNumber
501+
nb_scenarios = size(scenarios)[2]
502+
503+
costs = zeros(nb_scenarios)
504+
controls = zeros(TF,nb_scenarios)
505+
states = zeros(TF-1,nb_scenarios)
506+
507+
for k = 1:nb_scenarios
508+
costs[k],states[:,k], controls[:,k]= sdp_forward_simulation(SDPmodel,
509+
param,scenarios[:,k],model.initialState,value,display)
510+
end
511+
return costs, controls, states
512+
end
452513

453514
"""
454515
Simulation of optimal control given an initial state and an alea scenario
@@ -485,7 +546,7 @@ Returns :
485546
the controls applied to the system at each time step
486547
487548
"""
488-
function sdp_forward_simulation(model::SPModel,
549+
function sdp_forward_simulation(model::StochDynProgModel,
489550
param::SDPparameters,
490551
scenario::Array,
491552
X0::Array,

src/forwardBackwardIterations.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,23 @@ function forward_simulations(model::SPModel,
5858
param::SDDPparameters,
5959
V::Vector{PolyhedralFunction},
6060
solverProblems::Vector{JuMP.Model},
61-
xi::Array{Float64, 3},
61+
xi::Array{Float64},
6262
returnCosts=true::Bool,
6363
init=false::Bool,
6464
display=false::Bool)
65-
66-
# TODO: verify that loops are in the same order
65+
6766
T = model.stageNumber
6867
nb_forward = size(xi)[2]
6968

69+
if ndims(xi)!=3
70+
if ndims(xi)==2
71+
warn("noise scenario are not given in the right shape. Assumed to be real valued noise.")
72+
xi = reshape(xi,(T,nb_forward,1))
73+
else
74+
error("wrong dimension of noise scenarios")
75+
end
76+
end
77+
7078
stocks = zeros(T, nb_forward, model.dimStates)
7179
# We got T - 1 control, as terminal state is included into the total number
7280
# of stages.

src/noises.jl

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ end
155155

156156

157157
"""
158+
DEPRECATED
158159
Simulate n scenarios according to a given NoiseLaw
159160
160161
Parameters:
@@ -170,6 +171,7 @@ Returns :
170171
an Array of scenarios, scenarios[i,:] being the ith noise scenario
171172
"""
172173
function generate_scenarios(laws::Vector{NoiseLaw}, n::Int64)
174+
warn("deprecated generate_scenarios use simulate_scenarios")
173175
if n <= 0
174176
error("negative number of simulations")
175177
end
@@ -187,8 +189,43 @@ function generate_scenarios(laws::Vector{NoiseLaw}, n::Int64)
187189
return scenarios
188190
end
189191

192+
"""
193+
Simulate n scenarios and return a 3D array
194+
195+
Parameters:
196+
- laws (Vector{NoiseLaw})
197+
Distribution laws corresponding to each timestep
198+
199+
- n (Int64)
200+
number of scenarios to simulate
190201
202+
Return:
203+
- scenarios Array{Float64, 3}
204+
scenarios[t,k,:] is the noise at time t for scenario k
191205
"""
206+
function simulate_scenarios(laws, n::Int64)
207+
T = length(laws)
208+
dimAlea = size(laws[1].support)[1]
209+
dims =(T,n,dimAlea)
210+
if typeof(laws) == Distributions.Normal
211+
scenarios = rand(laws, dims)
212+
else
213+
scenarios = zeros(dims)
214+
215+
for k=1:dims[2]
216+
for t=1:dims[1]
217+
gen = Categorical(laws[t].proba)
218+
scenarios[t, k, :] = laws[t].support[:, rand(gen)]
219+
end
220+
221+
end
222+
end
223+
224+
return scenarios
225+
end
226+
227+
"""
228+
DEPRECATED
192229
Simulate n scenarios and return a 3D array
193230
194231
@@ -205,7 +242,7 @@ Return:
205242
206243
"""
207244
function simulate_scenarios(laws, dims::Tuple)
208-
245+
warn("decrecated call to simulate_scenarios")
209246
if typeof(laws) == Distributions.Normal
210247
scenarios = rand(laws, dims)
211248
else

0 commit comments

Comments
 (0)