-
Notifications
You must be signed in to change notification settings - Fork 0
/
Example1.jl
326 lines (287 loc) · 11.6 KB
/
Example1.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#This implementation is to compute subgradients of the GMB relaxations of an
#original ODE system modified from [Scott and Barton, JOGO, 2013, Example~1]
#package declaration
using IntervalArithmetic, EAGO, EAGO.McCormick
using DifferentialEquations, JuMP, Ipopt
using Plots; plotly()
#Time horizon for the original ODE system
tSpan = (0.0,4.0)
#Tolerance for ODE solver
e1 = 1e-6
#number of state variables
N = 2
#number of uncertain parameters
M = 2
#Lower and upper bounds for parameters
pL = (-3.0, 0.21)
pU = (3.0, 0.5)
#The ODE relaxations will be drawn w.r.t. p1, at p2 = 0.4
stepSize = (pU[1]-pL[1])/50
pSpan = pL[1]:stepSize:pU[1]
p2 = 0.4
#initial value function for a component xi
function x_initial(p, i)
if i == 1
return 0 * p[1] + 1.0
elseif i == 2
return 0 * p[1] + 0.5
end
end
#right-hand side function for a component fi
function original_RHS(x, p, t, i)
if i == 1
dx = -(2+sin(p[1]/3))*(x[1])^2 + p[2]*x[1]*x[2]
elseif i == 2
dx = sin(p[1]/3)*(x[1])^2 - p[2]*abs(x[1]*x[2])
end
return dx
end
#Vector RHS of the original ODE system
function original_vector_RHS(dx,x,p,t)
for i = 1:1:N
dx[i] = original_RHS(x,p,t,i)
end
end
#function that computes the original ODE solution at a specific p
function compute_original(p)
x0Aug = [x_initial(p,1),x_initial(p,2)]
prob = ODEProblem(original_vector_RHS, x0Aug, tSpan, p)
sol = DifferentialEquations.solve(prob, BS3(),reltol = e1)
return sol.u[end,:]
end
#function that computes the parametric solution at tf
function compute_para_sol_original()
paraSolution = Array{Float64}(undef, 0, 1)
for i = 1:1:length(pSpan)
p = [pSpan[i],p2]
paraSolution = [paraSolution; compute_original(p)]
end
return paraSolution
end
#funciton that constructs the subgradient propagation system's RHS for the GMB relaxations
#x is [xL, xU, xcv, xcc, xcv_grad, xcc_grad]
#pcomp is [p, p_I]
function GMB_subgradients_RHS(dx, x, pcomp, t)
#construct unflattened McCormick and interval objects for x
x_IA = Array{Interval}(undef, N)
x_MC = Array{MC}(undef, N)
for i = 1:1:N
x_IA[i] = Interval(x[i], x[i+N])
Sveccv = @SVector zeros(M)
Sveccc = @SVector zeros(M)
for j = 1:1:M
Sveccv = setindex(Sveccv, x[4*N+(i-1)*M+j],j)
Sveccc = setindex(Sveccc, x[4*N+N*M+(i-1)*M+j],j)
end
x_MC[i] = MC{M,NS}(x[i+2*N], x[i+3*N], x_IA[i], Sveccv, Sveccc, false)
end
#compute RHS functions for (xL_i, xU_i) and (xcc_i, xcv_i) for each index i
for i = 1:1:N
#compute dxi_L
#flatten xi_IA to x_L
x_IA[i] = Interval(x[i], x[i])
dx_IA = original_RHS(x_IA, pcomp[1:M], t, i)
dx[i] = lo(dx_IA)
#compute dxi_U
#flatten xi_IA to x_U
x_IA[i] = Interval(x[i+N], x[i+N])
dx_IA = original_RHS(x_IA, pcomp[1:M], t, i)
dx[i+N] = hi(dx_IA)
#unflatten xi_IA
x_IA[i] = Interval(x[i], x[i+N])
#compute dxi_cv and dxi_cv_grad
#flatten xi_MC to xi_cv and xi_sub to xi_cv_grad
Sveccv = @SVector zeros(M)
for j = 1:1:M
Sveccv = setindex(Sveccv, x[4*N+(i-1)*M+j],j)
end
x_MC[i] = MC{M,NS}(x[i+2*N], x[i+2*N], x_IA[i], Sveccv, Sveccv, false)
dx_MC = original_RHS(x_MC, pcomp[M+1:2*M], t, i)
dx[i+2*N] = dx_MC.cv
for j = 1:1:M
dx[4*N+(i-1)*M+j] = dx_MC.cv_grad[j]
end
#compute dxi_cc and dxi_cc_grad
#flatten xi_MC to xi_cc and xi_sub to xi_cc_grad
Sveccc = @SVector zeros(M)
for j = 1:1:M
Sveccc = setindex(Sveccc, x[4*N+N*M+(i-1)*M+j],j)
end
x_MC[i] = MC{M,NS}(x[i+3*N], x[i+3*N], x_IA[i], Sveccc, Sveccc, false)
dx_MC = original_RHS(x_MC, pcomp[M+1:2*M], t, i)
dx[i+3*N] = dx_MC.cc
for j = 1:1:M
dx[4*N+N*M+(i-1)*M+j] = dx_MC.cc_grad[j]
end
#unlatten xi_MC
Sveccv = @SVector zeros(M)
Sveccc = @SVector zeros(M)
for j = 1:1:M
Sveccv = setindex(Sveccv, x[4*N+(i-1)*M+j],j)
Sveccc = setindex(Sveccc, x[4*N+N*M+(i-1)*M+j],j)
end
x_MC[i] = MC{M,NS}(x[i+2*N], x[i+3*N], x_IA[i],Sveccv, Sveccc, false)
#It is verified that the resulting ODE relaxations do not visit the discrete jump
#=
#discrete jump
if x[i+2*N] <= x[i]
display(1)
dx[i+2*N] = max(dx[i+2*N], dx[i])
end
if x[i+3*N] >= x[i+N]
display(1)
dx[i+3*N] = min(dx[i+3*N], dx[i+N])
end
=#
end
end
#function that solves the subgradient system at a specific p
function compute_GMB_subgradients(p)
#construct a parameter array pcomp:=[p_I, p_MC]
pcomp = []
for i = 1:1:M
pcomp = push!(pcomp, Interval(pL[i], pU[i]))
end
for i = 1:1:M
Svec = @SVector zeros(M)
Svec = setindex(Svec, 1.0, i)
pcomp = push!(pcomp, MC{M,NS}(p[i], p[i], Interval(pL[i], pU[i]),Svec,Svec,false))
end
#find the initial value [x0L, x0U, x0cv, x0cc] based on p_IA, p_MC and store in a
#vector x0_MCobj
x0_MCobj = Array{Float64}(undef, 4*N+2*N*M)
for i = 1:1:N
xi = x_initial(pcomp[M+1:2*M], i)
x0_MCobj[i] = lo(xi.Intv)
x0_MCobj[i+N] = hi(xi.Intv)
x0_MCobj[i+2*N] = xi.cv
x0_MCobj[i+3*N] = xi.cc
for j = 1:1:M
x0_MCobj[4*N+(i-1)*M+j] = xi.cv_grad[j]
x0_MCobj[4*N+N*M+(i-1)*M+j] = xi.cc_grad[j]
end
end
#solve the subgradient ODE problem
prob = ODEProblem(GMB_subgradients_RHS, x0_MCobj, tSpan, pcomp)
sol = DifferentialEquations.solve(prob,BS3(),reltol = e1)
return sol.u[end, :]
end
#function that computes the parametric solution of the subgradient system
function compute_para_sol_GMB_subgradients()
paraSolution = Array{Float64}(undef, 0, 1)
for i = 1:1:length(pSpan)
p = [pSpan[i],p2]
paraSolution = [paraSolution; compute_GMB_subgradients(p)]
end
return paraSolution
end
#function that returns ODE convex relaxations and subgradients at a specific p
function compute_GMBcv_subgradients(p,i)
xrelax = compute_GMB_subgradients(p)
xcv = xrelax[1][i+2*N]
xcv_sub = xrelax[1][4*N+(i-1)*M+1:4*N+(i-1)*M+2]
return xcv, xcv_sub
end
#function that evaluates a single point on a subtangent line of cv
function compute_point_subtangent_GMBcv(pref,p,xcv,xcv_sub,i)
#xcv,xcv_sub = compute_GMBcv_subgradients(pref,i)
return xcv + xcv_sub[1]*(p[1]-pref[1]) + xcv_sub[2]*(p[2]-pref[2])
end
#function that computes the whole subtangent line of cv
function compute_point_subtangent_GMBcv(pref,i)
xcv,xcv_sub = compute_GMBcv_subgradients(pref,i)
#subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecv = Array{Float64}(undef,length(subpSpan))
for j = 1:1:length(subpSpan)
p = [subpSpan[j],p2]
sublinecv[j] = compute_point_subtangent_GMBcv(pref,p,xcv,xcv_sub,i)
end
return sublinecv
end
#function that returns ODE concave relaxations and subgradients at a specific p
function compute_GMBcc_subgradients(p,i)
xrelax = compute_GMB_subgradients(p)
xcc = xrelax[1][i+3*N]
xcc_sub = xrelax[1][4*N+N*M+(i-1)*M+1:4*N+N*M+(i-1)*M+2]
return xcc, xcc_sub
end
#function that evaluates a single point on a subtangent line of cc
function compute_point_subtangent_GMBcc(pref,p,xcc,xcc_sub,i)
#xcv,xcv_sub = compute_GMBcv_subgradients(pref,i)
return xcc + xcc_sub[1]*(p[1]-pref[1]) + xcc_sub[2]*(p[2]-pref[2])
end
#function that computes the whole subtangent line of cc
function compute_whole_subtangent_GMBcc(pref,i)
xcc,xcc_sub = compute_GMBcc_subgradients(pref,i)
#subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecc = Array{Float64}(undef,length(subpSpan))
for j = 1:1:length(subpSpan)
p = [subpSpan[j],p2]
sublinecc[j] = compute_point_subtangent_GMBcc(pref,p,xcc,xcc_sub,i)
end
return sublinecc
end
#Command for computing
#compute the original parametric solution
solori = compute_para_sol_original()
mmtrixori = hcat(solori...)
#compute parametric ODE relaxations
solu = compute_para_sol_GMB_subgradients()
mmtrixSB = hcat(solu...)
#Plot
#Plot for x1
index = 1
#Plot original parametric solution and ODE relaxations
p1 = plot(pSpan, [mmtrixSB[index+2*N, :],mmtrixSB[index+3*N, :]],xlabel = "p<sub>1</sub>",ylabel = "x<sub>1</sub>",gridlinewidth = 2,guidefontsize = 15, xtickfontsize=15, ytickfontsize=15,line = (:red, :solid),linewidth = 2.5,framestyle=:box,label = false)
plot!(pSpan, mmtrixori[index,:], linewidth = 2.5,line = (:black, :dash), label = false)
#Compute subtangent line at reference points and plot
pref = [1.32,p2]
subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecv = compute_point_subtangent_GMBcv(pref,index)
sublinecc = compute_whole_subtangent_GMBcc(pref,index)
xcv,xcv_sub=compute_GMBcv_subgradients(pref,index)
xcc,xcc_sub=compute_GMBcc_subgradients(pref,index)
plot!([pref[1]], [xcv], seriestype = :scatter, color = :blue, label = false)
plot!([pref[1]], [xcc], seriestype = :scatter, color = :blue, label = false)
plot!(subpSpan, sublinecv, linewidth = 2.5,line = (:blue, :dot),label = false)
plot!(subpSpan, sublinecc, linewidth = 2.5,line = (:blue, :dot),label = false)
pref = [-0.84,p2]
subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecc = compute_whole_subtangent_GMBcc(pref,index)
sublinecv = compute_point_subtangent_GMBcv(pref,index)
xcv,xcv_sub=compute_GMBcv_subgradients(pref,index)
xcc,xcc_sub=compute_GMBcc_subgradients(pref,index)
plot!([pref[1]], [xcv], seriestype = :scatter, color = :blue, label = false)
plot!([pref[1]], [xcc], seriestype = :scatter, color = :blue, label = false)
plot!(subpSpan, sublinecv, linewidth = 2.5,line = (:blue, :dot),label = false)
plot!(subpSpan, sublinecc, linewidth = 2.5,line = (:blue, :dot),label = false)
#Plot for x2
index = 2
#Plot original parametric solution and ODE relaxations
p3 = plot(pSpan, mmtrixSB[index+2*N, :],xlabel = "p<sub>1</sub>",ylabel = "x<sub>2</sub>",gridlinewidth = 2,guidefontsize = 15, xtickfontsize=15, ytickfontsize=15,line = (:red, :solid),linewidth = 2.5,framestyle=:box,label = "GMB relaxations")
plot!(pSpan, mmtrixSB[index+3*N, :],line = (:red, :solid),linewidth = 2.5,label=false)
plot!(pSpan, mmtrixori[index,:], linewidth = 2.5,line = (:black, :dash), label = "Original model")
#Compute subtangent lines at reference points and plot
pref = [1.32,p2]
subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecv = compute_point_subtangent_GMBcv(pref,index)
sublinecc = compute_whole_subtangent_GMBcc(pref,index)
xcv,xcv_sub=compute_GMBcv_subgradients(pref,index)
xcc,xcc_sub=compute_GMBcc_subgradients(pref,index)
plot!([pref[1]], [xcv], seriestype = :scatter, color = :blue, label = false)
plot!([pref[1]], [xcc], seriestype = :scatter, color = :blue, label = false)
plot!(subpSpan, sublinecv, linewidth = 2.5,line = (:blue, :dot),label = false)
plot!(subpSpan, sublinecc, linewidth = 2.5,line = (:blue, :dot),label = false)
pref = [-0.72,p2]
subpSpan = pref[1]-5*stepSize:stepSize:pref[1]+5*stepSize
sublinecc = compute_whole_subtangent_GMBcc(pref,index)
sublinecv = compute_point_subtangent_GMBcv(pref,index)
xcv,xcv_sub=compute_GMBcv_subgradients(pref,index)
xcc,xcc_sub=compute_GMBcc_subgradients(pref,index)
plot!([pref[1]], [xcv], seriestype = :scatter, color = :blue, label = false)
plot!([pref[1]], [xcc], seriestype = :scatter, color = :blue, label = false)
plot!(subpSpan, sublinecv, linewidth = 2.5,line = (:blue, :dot),label = "Subtangents")
plot!(subpSpan, sublinecc, linewidth = 2.5,line = (:blue, :dot),label = false)
#Plot two subfigures
plot(p1, p3, layout = (1, 2))
plot!(legend=:outertopright, legendcolumns=3, tickfontsize=12,labelfontsize=12)