Hi all, I have a problem with improving the optimization speed of the JuMP model.
My optimization problem is defined as follows:
Below are some constants and assistant functions:
using Distributions, LinearAlgebra
using Plots, DataFrames, CSV, ShiftedArrays
using Parameters, QuantEcon
using JuMP, Ipopt
@consts begin
ℓ = 20
Ncell = 5
α_est, β_est = 0.1245, 4e-4
R0 = 0.1803
# for FC-DLC cycle
# Imin, Inom, Imax = 0.04, 0.7, 2.0
# RUL_min, RUL_max = 500, 500
Imin, Inom, Imax = 0.2, 0.7, 1
RUL_min, RUL_max = 100, 100
pct_FT = 0.1
# calculated by V_nom decreasing pct_FT percent
RUL_nom = 1788
FT = R0 + RUL_nom * α_est * β_est # equivalent FT in R
α_0, β_0 = α_est/ℓ, β_est*ℓ
Lmin_0 = 0.8036
Lnom_0 = 2.38
Lmax_0 = 3.08
# parameters used in parabola funciton for α
a, b = 0.04225, 0.2129
end
abstract type FCS end
mutable struct FCstack <: FCS
Rs::Float64
Lmax::Float64
done::Bool
end
FCS_aging_paras = @with_kw (K = R0*5.93e-7*30*5.39/(Lmax_0-Lmin_0), ΔR_ss=1.96e-5*2)
fc_params = FCS_aging_paras()
function rand_loads(cur_state, states, prob; step=2)
mc = MarkovChain(prob, states)
return simulate(mc, step, init=findfirst(==(cur_state), states))
end
The main optimization loop is define within function:
main optimization loop
function simulate_cycle(mode, runs)
for i in 1:runs
FC1 = FCstack(R0+0.01, Lmax_0, false)
FC2 = FCstack(R0, Lmax_0, false)
simulation_time = 0.0
Ns = 2
states = [4.2, 5.2] # 2.7, 5.2; 4.0,
transition_matrix = [0.0 1.0
1.0 0.0]
steps = [250, 350, 500]
t_chances = Categorical([0.3, 0.3, 0.4])
L0 = states[1]
L11 = L0 / Ns
L21 = L0 / Ns
Lmax_fc1 = Lmax_0
Lmax_fc2 = Lmax_0
Lmax_fc3 = Lmax_0
for _ in 1:1
if mode[1] == "dec"
d1 = 1 - FC1.done
d2 = 1 - FC2.done
# d3 = 1 - FC3.done
# for random loads
Ld = rand_loads(L0, states, transition_matrix)[end]
op_durations = steps[rand(t_chances)]
## how to modify opt model inplace?
model = Model(Ipopt.Optimizer)
set_silent(model)
lb = Lmin_0 / Ld
ub = Lmax_0 / Ld
@variable(model, lb<=x<=ub, start=0.5)
@variable(model, lb<=y<=ub, start=0.5)
# @variable(model, lb<=z<=ub, start=0.5)
@NLconstraint(model, x + y ==1)
# @NLconstraint(model, d1*u[1]*x + d2*u[2]*y==1)
w1 = (FT - FC2.Rs) / (2FT - FC1.Rs - FC2.Rs)
w2 = 1 - w1
# defined aging parameters
w_dL = 1 # weight term for load varying caused aging
# 23/04 currently used obj
@NLexpression(model, f0dL,
(w1 * (x*Ld-L11)^2 + w2 * (y*Ld-L21)^2) * fc_params.K * 3600) #+ w3 * (z*Ld-L31)^2
@NLexpression(model, α_x,
ifelse(x * Ld < Lnom_0, (a * (x* Ld-Lnom_0)^2 + α_0),
(b * (x* Ld-Lnom_0)^2 + α_0)))
@NLexpression(model, α_y,
ifelse(y * Ld < Lnom_0, (a * (y* Ld-Lnom_0)^2 + α_0),
(b * (y* Ld-Lnom_0)^2 + α_0)))
# @NLobjective(model, Min, obj(x, y)) ? how to include start-stop opt in this obj
@NLobjective(model, Min, f0dL * w_dL + (w1*α_x + w2*α_y)*β_0*op_durations)
optimize!(model)
L12_ratio = value(x)
L22_ratio = value(y)
# L32 = value(z*Ld)
elseif mode[1] == "ave"
# L12 = Ld / Ns
# L22 = Ld / Ns
L12_ratio = 1 / Ns
L22_ratio = 1 / Ns
# L32 = Ld / Ns
end
# for random loads and random durations
Ld = rand_loads(L0, states, transition_matrix)[end]
op_durations = steps[rand(t_chances)]
L12 = L12_ratio * Ld
L22 = L22_ratio * Ld
FC1.Rs += 1e-4
FC2.Rs += 2e-4
simulation_time += op_durations
L11 = L12
L21 = L22
L0 = copy(Ld)
end
return simulation_time / 3600
end
end
The optimization is running through:
simulate_cycle(["dec", "det"], 1)
I need to repeatedly run this optimization as shown in the above function: controlled by two for loops.
I found the optimization turn out to be very slow, I see in the JuMP optimization, for such issues usually need to implement an optimization model in place. I failed to do this.
Thanks for checking this problem!