Sorry no MWE, the full program has like 2000 lines.
Some pseudo-code goes like this:
using InfiniteOpt, JuMP, KNITRO
function solvePolicies(optimizer, # model optimizer
sets::modelSettings, # number of EVs, discrete time supports, etc.
data::Dict, # information for the model (mainly parameters), these are the devices (EV, BESS, PV, etc.), the costs (interests, capex, etc) and the revenues
)
# Sets
tend=sets.dTime[end]
t0=sets.dTime[1]; # initial time, can´t divide by 0
model = InfiniteModel(optimizer) # create model
# KNITRO attributes
set_optimizer_attributes(model,
"feastol" => 1e-3,
"mip_multistart"=> 1,
"mip_outlevel"=> 2,
"mip_method"=> 1,
"mip_heuristic_maxit"=>800,
)
set_time_limit_sec(model, 60*15);
# define cont t
@infinite_parameter(model, t in [t0, tend], supports = collect(sets.dTime), derivative_method = FiniteDifference(Forward(),true))
# Add variables, constraints, obj
model = build_model(model, sets, data); # <== this is were the magic happens
# Solve model
optimize!(model)
results = getResults(model) # save results
MOI.empty!(InfiniteOpt.backend(model)) # clean MOI
return results;
end;
function getResults(model)
x = all_variables(model)
xdf=DataFrame(
name = name.(x),
value = value.(x),
)
idx=findall(x->x=="",name.(x)) # find point variables
delete!(xdf, idx) # delete point variables
xdict=Dict{Any,Any}(Pair.(xdf.name, xdf.value))
merge!(xdict,Dict("t"=>supports(model[:t]), "γ_cont"=>value.(model[:γ_cont])))
return xdict
end
function rollingHorizon(W, # weights
Tw, # time window [days]
steps, # number of steps to move the window
Δt) # time length of each step [hr]
# Build the data dictionary
data=buildDict();
# Initialize
tend = 24*Tw; # [hr]
Dt=0:Δt:tend; Dt=Dt*3600; # time array in seconds
s=modelSettings(nEV=1:2, dTime=collect(Dt), costWeights=W);
results=Vector{Dict}(undef, steps); # allocate memory
for ts in 1:steps
# build+solve model
model=solvePolicies(KNITRO.Optimizer, s, data);
# Print solution summary
# solution_summary(optimizer_model(model))
results[ts]=getResults(model);
model=InfiniteModel();
# update data, which contains the initial conditions
data=update_measurements(results[ts], s, data);
# move time window
Dt = Dt .+ Δt*3600.0;
# update_forecasts.(data, Dt)
s.dTime=collect(Dt);
end
return results, data, s
end
Wgrid = 1;
Wloss = 2;
W=[Wgrid 1000 Wloss];
results, data, s=rollingHorizon(W, 1, 4, 1/4);