Skip to content

Commit 12d6f71

Browse files
authored
Merge pull request #108 from JuliaOpt/dev-nightly
Update stock-example
2 parents 06b31b2 + f8853df commit 12d6f71

File tree

3 files changed

+63
-31
lines changed

3 files changed

+63
-31
lines changed

examples/stock-example.jl

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,30 @@
1414
using StochDynamicProgramming, JuMP, Clp, Distributions
1515
println("library loaded")
1616

17-
run_sddp = true
18-
run_sdp = true
17+
run_sddp = true # false if you don't want to run sddp
18+
run_sdp = true # false if you don't want to run sdp
19+
run_ef = true # false if you don't want to run extensive formulation
1920

2021
######## Optimization parameters ########
2122
# choose the LP solver used.
2223
const SOLVER = ClpSolver()
2324
# const SOLVER = CplexSolver(CPX_PARAM_SIMDISPLAY=0) # require "using CPLEX"
2425

2526
# convergence test
26-
const MAX_ITER = 100 # maximum iteration of SDDP
27+
const MAX_ITER = 10 # number of iterations of SDDP
2728

2829
######## Stochastic Model Parameters ########
29-
const N_STAGES = 5
30-
const COSTS = rand(N_STAGES)
30+
const N_STAGES = 6 # number of stages of the SP problem
31+
const COSTS = rand(N_STAGES) # generating deterministic costs
3132

32-
const CONTROL_MAX = 0.5
33+
const CONTROL_MAX = 0.5 # bounds on the control
3334
const CONTROL_MIN = 0
3435

35-
const XI_MAX = 0.3
36+
const XI_MAX = 0.3 # bounds on the noise
3637
const XI_MIN = 0
37-
const N_XI = 10
38-
# initial stock
39-
const S0 = 0.5
38+
const N_XI = 10 # discretization of the noise
39+
40+
const S0 = 0.5 # initial stock
4041

4142
# create law of noises
4243
proba = 1/N_XI*ones(N_XI) # uniform probabilities
@@ -55,33 +56,42 @@ function cost_t(t, x, u, w)
5556
end
5657

5758
######## Setting up the SPmodel
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-
59+
s_bounds = [(0, 1)] # bounds on the state
60+
u_bounds = [(CONTROL_MIN, CONTROL_MAX)] # bounds on controls
61+
spmodel = LinearDynamicLinearCostSPmodel(N_STAGES,u_bounds,[S0],cost_t,dynamic,xi_laws)
62+
set_state_bounds(spmodel, s_bounds) # adding the bounds to the model
63+
println("Model set up")
6364

6465
######### Solving the problem via SDDP
6566
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
67+
println("Starting resolution by SDDP")
68+
paramSDDP = SDDPparameters(SOLVER, 10, 0, MAX_ITER) # 10 forward pass, stop at MAX_ITER
69+
V, pbs = solve_SDDP(spmodel, paramSDDP, 2) # display information every 2 iterations
6870
lb_sddp = StochDynamicProgramming.get_lower_bound(spmodel, paramSDDP, V)
69-
println("Lower bound obtained by SDDP: "*string(lb_sddp))
71+
println("Lower bound obtained by SDDP: "*string(round(lb_sddp,4)))
7072
end
7173

7274
######### Solving the problem via Dynamic Programming
7375
if run_sdp
74-
stateSteps = [0.01]
75-
controlSteps = [0.01]
76+
println("Starting resolution by SDP")
77+
stateSteps = [0.01] # discretization step of the state
78+
controlSteps = [0.01] # discretization step of the control
7679
infoStruct = "HD" # noise at time t is known before taking the decision at time t
77-
7880
paramSDP = SDPparameters(spmodel, stateSteps, controlSteps, infoStruct)
7981
Vs = solve_DP(spmodel,paramSDP, 1)
80-
lb_sdp = StochDynamicProgramming.get_bellman_value(spmodel,paramSDP,Vs)
81-
println("Value obtained by SDP: "*string(lb_sdp))
82+
value_sdp = StochDynamicProgramming.get_bellman_value(spmodel,paramSDP,Vs)
83+
println("Value obtained by SDP: "*string(round(value_sdp,4)))
84+
end
85+
86+
if run_ef
87+
println("Starting resolution by Extensive Formulation")
88+
value_ef = extensive_formulation(spmodel, paramSDDP)[1]
89+
println("Value obtained by Extensive Formulation: "*string(round(value_ef,4)))
90+
println("Relative error of SDP value: "*string(100*round(value_sdp/value_ef-1,4))*"%")
91+
println("Relative error of SDDP lower bound: "*string(100*round(lb_sddp/value_ef-1,4))*"%")
8292
end
8393

84-
######### Comparing the solution
94+
######### Comparing the solutions on simulated scenarios.
8595
scenarios = StochDynamicProgramming.simulate_scenarios(xi_laws,1000)
8696
if run_sddp
8797
costsddp, stocks = forward_simulations(spmodel, paramSDDP, pbs, scenarios)
@@ -90,5 +100,6 @@ if run_sdp
90100
costsdp, states, stocks =sdp_forward_simulation(spmodel,paramSDP,scenarios,Vs)
91101
end
92102
if run_sddp && run_sdp
93-
println(mean(costsddp-costsdp))
103+
println("Simulated relative difference between sddp and sdp: "
104+
*string(round(200*mean(costsddp-costsdp)/mean(costsddp+costsdp),3))*"%")
94105
end

src/SDDPoptimize.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ fulfilled.
3939
function solve_SDDP(model::SPModel, param::SDDPparameters, display=0::Int64)
4040
# initialize value functions:
4141
V, problems = initialize_value_functions(model, param)
42+
println("initial value function intialized")
4243
# Run SDDP upon example:
4344
sddp_stats = run_SDDP!(model, param, V, problems, display)
4445
return V, problems, sddp_stats
@@ -128,10 +129,16 @@ function run_SDDP!(model::SPModel,
128129
push!(stats.upper_bounds, upb)
129130

130131
if (display > 0) && (iteration_count%display==0)
131-
println("Pass number ", iteration_count,
132+
if upb < Inf
133+
println("Pass number ", iteration_count,
132134
"\tUpper-bound: ", upb,
133135
"\tLower-bound: ", round(stats.lower_bounds[end], 4),
134136
"\tTime: ", round(stats.exectime[end], 2),"s")
137+
else
138+
println("Pass number ", iteration_count,
139+
"\tLower-bound: ", round(stats.lower_bounds[end], 4),
140+
"\tTime: ", round(stats.exectime[end], 2),"s")
141+
end
135142
end
136143

137144
end
@@ -313,7 +320,7 @@ function initialize_value_functions(model::SPModel,
313320
param::SDDPparameters)
314321

315322
solverProblems = build_models(model, param)
316-
323+
println("model builded")
317324
V = PolyhedralFunction[
318325
PolyhedralFunction([], Array{Float64}(0, model.dimStates), 0) for i in 1:model.stageNumber]
319326

src/extensiveFormulation.jl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ measurability constraints.
1313
# Arguments:
1414
* `model::SPModel`
1515
* `param::SDDPparameters`
16+
# Returns
17+
* `objective value`
18+
* `first control`
19+
* `status of optimization problem`
1620
"""
1721
function extensive_formulation(model, param)
1822

@@ -49,12 +53,16 @@ function extensive_formulation(model, param)
4953
end
5054
end
5155
end
52-
53-
#Instantiate the problem creating dynamic constraint at each node
54-
for t = 1 : (T)
56+
#Add state constraints
57+
for t = 1 :(T+1)
5558
for n = 1 : N[t]
5659
@constraint(mod,[x[t,DIM_STATE*(n-1)+k] for k = 1:DIM_STATE] .>= [model.xlim[k][1] for k = 1:DIM_STATE])
5760
@constraint(mod,[x[t,DIM_STATE*(n-1)+k] for k = 1:DIM_STATE] .<= [model.xlim[k][2] for k = 1:DIM_STATE])
61+
end
62+
end
63+
#Instantiate the problem creating dynamic constraint at each node
64+
for t = 1 : (T)
65+
for n = 1 : N[t]
5866
for xi = 1 : laws[t].supportSize
5967
m = (n-1)*laws[t].supportSize+xi
6068

@@ -83,12 +91,18 @@ function extensive_formulation(model, param)
8391
@constraint(mod, [x[1,k] for k = 1:DIM_STATE] .== X_init)
8492

8593
#Define the objective of the function
86-
@objective(mod, Min, sum{ sum{proba[t][laws[t].supportSize*(n-1)+k]*c[t,laws[t].supportSize*(n-1)+k],k = 1:laws[t].supportSize} , t = 1:T, n=1:div(N[t+1],laws[t].supportSize)})
94+
@objective(mod, Min,
95+
sum{
96+
sum{ proba[t][laws[t].supportSize*(n-1)+k]*c[t,laws[t].supportSize*(n-1)+k],
97+
k = 1:laws[t].supportSize},
98+
t = 1:T, n=1:div(N[t+1],laws[t].supportSize)}
99+
)
87100

88101
status = solve(mod)
89102
solved = (status == :Optimal)
90103

91104
if solved
105+
println("EF value: "*string(getobjectivevalue(mod)))
92106
firstControl = collect(values(getvalue(u)))[1:DIM_CONTROL*laws[1].supportSize]
93107
return getobjectivevalue(mod), firstControl, status
94108
else

0 commit comments

Comments
 (0)