From b6e790a28b87a2af22c14315b8970f506a963d89 Mon Sep 17 00:00:00 2001
From: odow <o.dowson@gmail.com>
Date: Fri, 30 Aug 2024 12:08:39 +1200
Subject: [PATCH] Many updates and simplifications

---
 docs/make.jl                                  |   1 +
 .../tutorials/algorithms/rolling_horizon.csv  | 338 +++++++++---------
 .../tutorials/algorithms/rolling_horizon.jl   | 195 ++++------
 3 files changed, 237 insertions(+), 297 deletions(-)

diff --git a/docs/make.jl b/docs/make.jl
index c52062d7bd3..54ea801b60b 100644
--- a/docs/make.jl
+++ b/docs/make.jl
@@ -377,6 +377,7 @@ const _PAGES = [
             "tutorials/algorithms/benders_decomposition.md",
             "tutorials/algorithms/cutting_stock_column_generation.md",
             "tutorials/algorithms/tsp_lazy_constraints.md",
+            "tutorials/algorithms/rolling_horizon.md",
             "tutorials/algorithms/parallelism.md",
         ],
         "Applications" => [
diff --git a/docs/src/tutorials/algorithms/rolling_horizon.csv b/docs/src/tutorials/algorithms/rolling_horizon.csv
index dfae1396ab3..d74486700ee 100644
--- a/docs/src/tutorials/algorithms/rolling_horizon.csv
+++ b/docs/src/tutorials/algorithms/rolling_horizon.csv
@@ -1,169 +1,169 @@
-t,demand_MW,solar_pu
-2000-01-01T00:00:00,51.6,0
-2000-01-01T01:00:00,49.2,0
-2000-01-01T02:00:00,46.5,0
-2000-01-01T03:00:00,44.3,0
-2000-01-01T04:00:00,43.3,0
-2000-01-01T05:00:00,42.1,0
-2000-01-01T06:00:00,39.8,0
-2000-01-01T07:00:00,40.2,0
-2000-01-01T08:00:00,41.3,0.212560386
-2000-01-01T09:00:00,45,0.608695652
-2000-01-01T10:00:00,49.3,0.845410628
-2000-01-01T11:00:00,54.3,0.995169082
-2000-01-01T12:00:00,56,1
-2000-01-01T13:00:00,54.9,0.763285024
-2000-01-01T14:00:00,53.3,0.309178744
-2000-01-01T15:00:00,53.5,0.009661836
-2000-01-01T16:00:00,57.5,0
-2000-01-01T17:00:00,65,0
-2000-01-01T18:00:00,66.2,0
-2000-01-01T19:00:00,64.5,0
-2000-01-01T20:00:00,61,0
-2000-01-01T21:00:00,59,0
-2000-01-01T22:00:00,58.7,0
-2000-01-01T23:00:00,54.1,0
-2000-01-02T00:00:00,49.7,0
-2000-01-02T01:00:00,46.5,0
-2000-01-02T02:00:00,44.8,0
-2000-01-02T03:00:00,44.5,0
-2000-01-02T04:00:00,46,0
-2000-01-02T05:00:00,48.6,0
-2000-01-02T06:00:00,52.6,0
-2000-01-02T07:00:00,59,0
-2000-01-02T08:00:00,65.1,0.096618357
-2000-01-02T09:00:00,70.1,0.256038647
-2000-01-02T10:00:00,73.5,0.391304348
-2000-01-02T11:00:00,76.2,0.47826087
-2000-01-02T12:00:00,76.8,0.531400966
-2000-01-02T13:00:00,75.1,0.434782609
-2000-01-02T14:00:00,73.2,0.202898551
-2000-01-02T15:00:00,72.5,0.014492754
-2000-01-02T16:00:00,75.2,0
-2000-01-02T17:00:00,80.7,0
-2000-01-02T18:00:00,80.7,0
-2000-01-02T19:00:00,77.5,0
-2000-01-02T20:00:00,71.3,0
-2000-01-02T21:00:00,67.6,0
-2000-01-02T22:00:00,65.8,0
-2000-01-02T23:00:00,60.4,0
-2000-01-03T00:00:00,54.7,0
-2000-01-03T01:00:00,50.9,0
-2000-01-03T02:00:00,48.5,0
-2000-01-03T03:00:00,47.7,0
-2000-01-03T04:00:00,48.2,0
-2000-01-03T05:00:00,48.5,0
-2000-01-03T06:00:00,49.1,0
-2000-01-03T07:00:00,53.3,0
-2000-01-03T08:00:00,58.9,0.09178744
-2000-01-03T09:00:00,64.6,0.265700483
-2000-01-03T10:00:00,68.8,0.367149758
-2000-01-03T11:00:00,72,0.400966184
-2000-01-03T12:00:00,72.4,0.347826087
-2000-01-03T13:00:00,70.9,0.251207729
-2000-01-03T14:00:00,69.5,0.111111111
-2000-01-03T15:00:00,69.5,0.009661836
-2000-01-03T16:00:00,72.5,0
-2000-01-03T17:00:00,77.3,0
-2000-01-03T18:00:00,77.4,0
-2000-01-03T19:00:00,73.9,0
-2000-01-03T20:00:00,68,0
-2000-01-03T21:00:00,64.1,0
-2000-01-03T22:00:00,62.8,0
-2000-01-03T23:00:00,58.1,0
-2000-01-04T00:00:00,52.8,0
-2000-01-04T01:00:00,49.1,0
-2000-01-04T02:00:00,47,0
-2000-01-04T03:00:00,45.9,0
-2000-01-04T04:00:00,46.1,0
-2000-01-04T05:00:00,45.5,0
-2000-01-04T06:00:00,44.1,0
-2000-01-04T07:00:00,46.5,0.004830918
-2000-01-04T08:00:00,50.3,0.256038647
-2000-01-04T09:00:00,55.6,0.700483092
-2000-01-04T10:00:00,60.3,0.888888889
-2000-01-04T11:00:00,65.6,0.93236715
-2000-01-04T12:00:00,65.9,0.787439614
-2000-01-04T13:00:00,63.2,0.550724638
-2000-01-04T14:00:00,60.7,0.275362319
-2000-01-04T15:00:00,60.1,0.019323671
-2000-01-04T16:00:00,63.4,0
-2000-01-04T17:00:00,71.3,0
-2000-01-04T18:00:00,73.1,0
-2000-01-04T19:00:00,70.9,0
-2000-01-04T20:00:00,66.8,0
-2000-01-04T21:00:00,64.2,0
-2000-01-04T22:00:00,63.9,0
-2000-01-04T23:00:00,58.9,0
-2000-01-05T00:00:00,54,0
-2000-01-05T01:00:00,50.7,0
-2000-01-05T02:00:00,49.4,0
-2000-01-05T03:00:00,49.6,0
-2000-01-05T04:00:00,51.7,0
-2000-01-05T05:00:00,56.9,0
-2000-01-05T06:00:00,66.2,0
-2000-01-05T07:00:00,76.3,0.009661836
-2000-01-05T08:00:00,82,0.29468599
-2000-01-05T09:00:00,83.8,0.628019324
-2000-01-05T10:00:00,85.9,0.777777778
-2000-01-05T11:00:00,87.7,0.893719807
-2000-01-05T12:00:00,87.7,0.874396135
-2000-01-05T13:00:00,86.2,0.743961353
-2000-01-05T14:00:00,84.7,0.444444444
-2000-01-05T15:00:00,83.9,0.057971014
-2000-01-05T16:00:00,85.9,0
-2000-01-05T17:00:00,92,0
-2000-01-05T18:00:00,92,0
-2000-01-05T19:00:00,89,0
-2000-01-05T20:00:00,82,0
-2000-01-05T21:00:00,77.2,0
-2000-01-05T22:00:00,74.1,0
-2000-01-05T23:00:00,67,0
-2000-01-06T00:00:00,61.8,0
-2000-01-06T01:00:00,58,0
-2000-01-06T02:00:00,56.3,0
-2000-01-06T03:00:00,56.4,0
-2000-01-06T04:00:00,57.7,0
-2000-01-06T05:00:00,60.6,0
-2000-01-06T06:00:00,67.4,0
-2000-01-06T07:00:00,75.7,0.009661836
-2000-01-06T08:00:00,79.7,0.256038647
-2000-01-06T09:00:00,81.7,0.584541063
-2000-01-06T10:00:00,84.2,0.821256039
-2000-01-06T11:00:00,86.3,0.942028986
-2000-01-06T12:00:00,86,0.884057971
-2000-01-06T13:00:00,83.8,0.661835749
-2000-01-06T14:00:00,81.5,0.328502415
-2000-01-06T15:00:00,80.9,0.028985507
-2000-01-06T16:00:00,83.8,0
-2000-01-06T17:00:00,90.7,0
-2000-01-06T18:00:00,90.7,0
-2000-01-06T19:00:00,88.2,0
-2000-01-06T20:00:00,82.1,0
-2000-01-06T21:00:00,77.2,0
-2000-01-06T22:00:00,73.9,0
-2000-01-06T23:00:00,67.5,0
-2000-01-07T00:00:00,61.8,0
-2000-01-07T01:00:00,57.9,0
-2000-01-07T02:00:00,56.9,0
-2000-01-07T03:00:00,57.5,0
-2000-01-07T04:00:00,59.2,0
-2000-01-07T05:00:00,64.8,0
-2000-01-07T06:00:00,77.9,0
-2000-01-07T07:00:00,89.3,0.004830918
-2000-01-07T08:00:00,94.1,0.154589372
-2000-01-07T09:00:00,94.4,0.434782609
-2000-01-07T10:00:00,95.9,0.589371981
-2000-01-07T11:00:00,97.3,0.70531401
-2000-01-07T12:00:00,96.7,0.647342995
-2000-01-07T13:00:00,95.6,0.531400966
-2000-01-07T14:00:00,93.7,0.265700483
-2000-01-07T15:00:00,92.7,0.028985507
-2000-01-07T16:00:00,94,0
-2000-01-07T17:00:00,100,0
-2000-01-07T18:00:00,99.2,0
-2000-01-07T19:00:00,95.8,0
-2000-01-07T20:00:00,88.9,0
-2000-01-07T21:00:00,83.3,0
-2000-01-07T22:00:00,79.2,0
-2000-01-07T23:00:00,71.3,0
+day,hour,demand_MW,solar_pu
+01,00,51.6,0
+01,01,49.2,0
+01,02,46.5,0
+01,03,44.3,0
+01,04,43.3,0
+01,05,42.1,0
+01,06,39.8,0
+01,07,40.2,0
+01,08,41.3,0.212560386
+01,09,45,0.608695652
+01,10,49.3,0.845410628
+01,11,54.3,0.995169082
+01,12,56,1
+01,13,54.9,0.763285024
+01,14,53.3,0.309178744
+01,15,53.5,0.009661836
+01,16,57.5,0
+01,17,65,0
+01,18,66.2,0
+01,19,64.5,0
+01,20,61,0
+01,21,59,0
+01,22,58.7,0
+01,23,54.1,0
+02,00,49.7,0
+02,01,46.5,0
+02,02,44.8,0
+02,03,44.5,0
+02,04,46,0
+02,05,48.6,0
+02,06,52.6,0
+02,07,59,0
+02,08,65.1,0.096618357
+02,09,70.1,0.256038647
+02,10,73.5,0.391304348
+02,11,76.2,0.47826087
+02,12,76.8,0.531400966
+02,13,75.1,0.434782609
+02,14,73.2,0.202898551
+02,15,72.5,0.014492754
+02,16,75.2,0
+02,17,80.7,0
+02,18,80.7,0
+02,19,77.5,0
+02,20,71.3,0
+02,21,67.6,0
+02,22,65.8,0
+02,23,60.4,0
+03,00,54.7,0
+03,01,50.9,0
+03,02,48.5,0
+03,03,47.7,0
+03,04,48.2,0
+03,05,48.5,0
+03,06,49.1,0
+03,07,53.3,0
+03,08,58.9,0.09178744
+03,09,64.6,0.265700483
+03,10,68.8,0.367149758
+03,11,72,0.400966184
+03,12,72.4,0.347826087
+03,13,70.9,0.251207729
+03,14,69.5,0.111111111
+03,15,69.5,0.009661836
+03,16,72.5,0
+03,17,77.3,0
+03,18,77.4,0
+03,19,73.9,0
+03,20,68,0
+03,21,64.1,0
+03,22,62.8,0
+03,23,58.1,0
+04,00,52.8,0
+04,01,49.1,0
+04,02,47,0
+04,03,45.9,0
+04,04,46.1,0
+04,05,45.5,0
+04,06,44.1,0
+04,07,46.5,0.004830918
+04,08,50.3,0.256038647
+04,09,55.6,0.700483092
+04,10,60.3,0.888888889
+04,11,65.6,0.93236715
+04,12,65.9,0.787439614
+04,13,63.2,0.550724638
+04,14,60.7,0.275362319
+04,15,60.1,0.019323671
+04,16,63.4,0
+04,17,71.3,0
+04,18,73.1,0
+04,19,70.9,0
+04,20,66.8,0
+04,21,64.2,0
+04,22,63.9,0
+04,23,58.9,0
+05,00,54,0
+05,01,50.7,0
+05,02,49.4,0
+05,03,49.6,0
+05,04,51.7,0
+05,05,56.9,0
+05,06,66.2,0
+05,07,76.3,0.009661836
+05,08,82,0.29468599
+05,09,83.8,0.628019324
+05,10,85.9,0.777777778
+05,11,87.7,0.893719807
+05,12,87.7,0.874396135
+05,13,86.2,0.743961353
+05,14,84.7,0.444444444
+05,15,83.9,0.057971014
+05,16,85.9,0
+05,17,92,0
+05,18,92,0
+05,19,89,0
+05,20,82,0
+05,21,77.2,0
+05,22,74.1,0
+05,23,67,0
+06,00,61.8,0
+06,01,58,0
+06,02,56.3,0
+06,03,56.4,0
+06,04,57.7,0
+06,05,60.6,0
+06,06,67.4,0
+06,07,75.7,0.009661836
+06,08,79.7,0.256038647
+06,09,81.7,0.584541063
+06,10,84.2,0.821256039
+06,11,86.3,0.942028986
+06,12,86,0.884057971
+06,13,83.8,0.661835749
+06,14,81.5,0.328502415
+06,15,80.9,0.028985507
+06,16,83.8,0
+06,17,90.7,0
+06,18,90.7,0
+06,19,88.2,0
+06,20,82.1,0
+06,21,77.2,0
+06,22,73.9,0
+06,23,67.5,0
+07,00,61.8,0
+07,01,57.9,0
+07,02,56.9,0
+07,03,57.5,0
+07,04,59.2,0
+07,05,64.8,0
+07,06,77.9,0
+07,07,89.3,0.004830918
+07,08,94.1,0.154589372
+07,09,94.4,0.434782609
+07,10,95.9,0.589371981
+07,11,97.3,0.70531401
+07,12,96.7,0.647342995
+07,13,95.6,0.531400966
+07,14,93.7,0.265700483
+07,15,92.7,0.028985507
+07,16,94,0
+07,17,100,0
+07,18,99.2,0
+07,19,95.8,0
+07,20,88.9,0
+07,21,83.3,0
+07,22,79.2,0
+07,23,71.3,0
diff --git a/docs/src/tutorials/algorithms/rolling_horizon.jl b/docs/src/tutorials/algorithms/rolling_horizon.jl
index 535f4f07bc2..ae81a346369 100644
--- a/docs/src/tutorials/algorithms/rolling_horizon.jl
+++ b/docs/src/tutorials/algorithms/rolling_horizon.jl
@@ -110,12 +110,12 @@ import StatsPlots
 # optimization window and the move forward.
 #
 # **Optimization Window** (optimization_window): It defines how many periods
-# (e.g., hours) we will optimize each time. For this example, we set the default
+# (for example, hours) we will optimize each time. For this example, we set the default
 # value in 48h, meaning we will optimize two days each time.
 
 optimization_window = 48
 
-# **Move Forward** (move_forward): It defines how many periods (e.g., hours) we
+# **Move Forward** (move_forward): It defines how many periods (for example, hours) we
 # will move forward to optimize the next optimization window. For this example,
 # we set the default value in 24h, meaning we will move 1 day ahead each time.
 
@@ -124,7 +124,7 @@ move_forward = 24
 # Note that the move forward parameter must be lower or equal to the
 # optimization window parameter to work correctly.
 
-@assert optimization_window >= move_forward "optimization_window must be greater or equal to move_forward"
+@assert optimization_window >= move_forward
 
 # Let's explore the input data in file [rolling_horizon.csv](rolling_horizon.csv).
 # We have a total time horizon of a week (i.e., 168h), an electricity demand,
@@ -133,7 +133,7 @@ move_forward = 24
 filename = joinpath(@__DIR__, "rolling_horizon.csv")
 time_series = CSV.read(filename, DataFrames.DataFrame);
 
-# We define the solar investment (e.g., 150 MW) to determine the solar
+# We define the solar investment (for example, 150 MW) to determine the solar
 # production during the operation optimization step.
 #
 # In addition, we can determine some basic information about the rolling
@@ -150,168 +150,106 @@ time_series.solar_MW = solar_investment * time_series.solar_pu
 
 ## input data calculation for the Rolling Horizon
 total_time_length = size(time_series, 1)
-number_of_windows = ceil(Int, total_time_length / move_forward)
-println("number of windows:", number_of_windows)
+println("number of windows:", ceil(Int, total_time_length / move_forward))
 
 #-
-p1 = Plots.plot(
-    time_series.t,
-    [time_series.demand_MW, time_series.solar_MW];
-    ylabel = "MW",
-    label = ["demand" "solar"],
-    color = [:ivory4 :darkorange1],
+x_series = 1:total_time_length
+y_series = [time_series.demand_MW, time_series.solar_MW]
+plot_1 = Plots.plot(x_series, y_series; label = ["demand" "solar"])
+plot_2 = Plots.plot(x_series, y_series; label = false)
+window = [0, optimization_window]
+Plots.vspan!(plot_1, window; alpha = 0.25, label = false)
+Plots.vspan!(plot_2, move_forward .+ window; alpha = 0.25, label = false)
+text_1 = Plots.text("optimization\n  window 1", :top, :left, 8)
+Plots.annotate!(plot_1, 18, time_series.solar_MW[12], text_1)
+text_2 = Plots.text("optimization\n  window 2", :top, :left, 8)
+Plots.annotate!(plot_2, 42, time_series.solar_MW[12], text_2)
+Plots.plot(
+    plot_1,
+    plot_2;
+    layout = (2, 1),
     linewidth = 3,
-    ylims = (0, solar_investment),
     xticks = 0:12:total_time_length,
-)
-Plots.vspan!(p1, [1, optimization_window]; alpha = 0.25, label = "")
-Plots.annotate!(
-    p1,
-    18,
-    time_series[12, :solar_MW],
-    Plots.text("optimization\n   window 1", :top, :left, 8),
-)
-p2 = Plots.plot(
-    time_series.t,
-    [time_series.demand_MW, time_series.solar_MW];
     xlabel = "Hours",
     ylabel = "MW",
-    label = ["" ""],
-    color = [:ivory4 :darkorange1],
-    linewidth = 3,
-    ylims = (0, solar_investment),
-    xticks = 0:12:total_time_length,
-)
-Plots.vspan!(
-    p2,
-    [move_forward, move_forward + optimization_window];
-    alpha = 0.25,
-    label = "",
-)
-Plots.annotate!(
-    p2,
-    42,
-    time_series[12, :solar_MW],
-    Plots.text("optimization\n   window 2", :top, :left, 8),
 )
-Plots.plot!(
-    p2,
-    [1; move_forward],
-    [100; 100];
-    arrow = 2,
-    label = "",
-    c = :black,
-)
-Plots.annotate!(p2, 5, 130, Plots.text(" move\nforward", :top, :left, 8))
-Plots.plot(p1, p2; layout = (2, 1))
 
 # ## Rolling horizon first window
 #
-# We first sample the initial input data and get the parameter values for the
-# first optimization window.
-#
-# We also create a helper index `t_minus_1` to get easy access to the previous
-# hour using the function `mod1`.
-
-## Create data of the first window
-time_series_filter = 1:optimization_window
-availability = time_series.solar_pu[time_series_filter]
-demand = time_series.demand_MW[time_series_filter]
-## Create index t and t-1
-t = 1:optimization_window
-t_minus_1 =
-    mod1.(optimization_window:(2*optimization_window-1), optimization_window)
-
 # We have all the information we need to create and optimize the first window in
 # the model.
 
 model = Model(() -> POI.Optimizer(HiGHS.Optimizer()))
 set_silent(model)
-@variable(model, 0 <= i)
-@variable(model, 0 <= r[t])
-@variable(model, 0 <= p[t] <= 150)
-@variable(model, 0 <= s[t] <= 40)
-@variable(model, 0 <= c[t] <= 10)
-@variable(model, 0 <= d[t] <= 10)
-@variable(model, D[t] in Parameter.(demand[t]))
-@variable(model, A[t] in Parameter.(availability[t]))
-@variable(model, So in Parameter(0.0))
-@constraint(model, balance, p[t] .+ r[t] .+ d[t] .== D[t] .+ c[t])
-@constraint(
+@variables(model, begin
+    i == solar_investment
+    0 <= r[1:optimization_window]
+    0 <= p[1:optimization_window] <= 150
+    0 <= s[1:optimization_window] <= 40
+    0 <= c[1:optimization_window] <= 10
+    0 <= d[1:optimization_window] <= 10
+    ## Initialize empty parameters. These values will get updated layer
+    D[t in 1:optimization_window] in Parameter(0)
+    A[t in 1:optimization_window] in Parameter(0)
+    So in Parameter(0)
+end)
+@constraints(
     model,
-    storage[t in 2:optimization_window],
-    s[t] == s[t-1] + 0.9 * c[t] - d[t] / 0.9
+    begin
+        p .+ r .+ d .== D .+ c
+        s[1] == So + 0.9 * c[1] - d[1] / 0.9
+        [t in 2:optimization_window], s[t] == s[t-1] + 0.9 * c[t] - d[t] / 0.9
+        r .<= A .* i
+    end
 )
-@constraint(model, init_storage, s[1] == So + 0.9 * c[1] - d[1] / 0.9)
-@constraint(model, max_ava, r[t] .<= A[t] * i)
-@objective(model, Min, 100 * i + sum(50 * p[t]))
-fix(i, solar_investment; force = true)
-optimize!(model)
+@objective(model, Min, 100 * i + 50 * sum(p))
+model
 
 # After the optimization, we can store the results in vectors. It's important to
 # note that despite optimizing for 48 hours (the default value), we only store
-# the values for the "move forward" parameter (e.g., 24 hours or one day using
-# the default value). This approach ensures that there is a buffer of additional
-# periods or hours beyond the "move forward" parameter to prevent the storage
-# from depleting entirely at the end of the specified hours.
+# the values for the "move forward" parameter (for example, 24 hours or one day
+# using the default value). This approach ensures that there is a buffer of
+# additional periods or hours beyond the "move forward" parameter to prevent the
+# storage from depleting entirely at the end of the specified hours.
 
-objective_function_per_window = zeros(number_of_windows)
+objective_function_per_window = Float64[]
 renewable_production = zeros(total_time_length)
 storage_level = zeros(total_time_length)
 
-# Store results from the first window
-renewable_production[1:move_forward] = value.(model[:r])[1:move_forward]
-storage_level[1:move_forward] = value.(model[:s])[1:move_forward]
-objective_function_per_window[1] = objective_value(model)
-println("Objective function first window: ", objective_function_per_window[1])
-
 # ### Rolling horizon for the following windows
 #
 # For the following windows on the horizon, we:
 #
-# 1. Update the parameter values from the input data for that window
-# 2. Update the parameters in the models using the ParametricOptInterface.jl
-# 3. Solve the model for that window
-# 4. Store the results
-#
-# Although this is a small problem, the benefits of using
-# ParametricOptInterface.jl can be seen in the simplex iterations in the first
-# window compared to the ones in the subsequent ones.
+# 1. Update the parameters in the models using the ParametricOptInterface.jl
+# 2. Solve the model for that window
+# 3. Store the results
 
-for window in 2:number_of_windows
-    # Update window data
-    window_start = Int(1 + (window - 1) * move_forward)
-    window_end = Int(window_start + optimization_window - 1)
-    time_series_filter = mod1.(window_start:window_end, total_time_length)
-    availability = time_series.solar_pu[time_series_filter]
-    demand = time_series.demand_MW[time_series_filter]
-    initial_storage = storage_level[window_start-1]
-    # Update parameters in the model
-    MOI.set.(model, POI.ParameterValue(), model[:D], demand)
-    MOI.set.(model, POI.ParameterValue(), model[:A], availability)
-    MOI.set(model, POI.ParameterValue(), model[:So], initial_storage)
-    # Optimize again
+for offset in 0:move_forward:total_time_length-1
+    ## Step 1: update the parameter values over the optimization_window
+    for t in 1:optimization_window
+        row = mod1(offset + t, size(time_series, 1))
+        set_parameter_value(model[:D][t], time_series[row, :demand_MW])
+        set_parameter_value(model[:A][t], time_series[row, :solar_pu])
+    end
+    set_parameter_value(model[:So], get(storage_level, offset, 0))
+    ## Step 2: solve the model
     optimize!(model)
-    # Store results for each window
-    window_end_output =
-        minimum([Int(window_start + move_forward - 1) total_time_length])
-    output_filter = window_start:window_end_output
-    last_output_value =
-        minimum([move_forward (window_end_output - window_start + 1)])
-    renewable_production[output_filter] = value.(model[:r])[1:last_output_value]
-    storage_level[output_filter] = value.(model[:s])[1:last_output_value]
-    objective_function_per_window[window] = objective_value(model)
+    ## Step 3: store the results of the move_forward values
+    push!(objective_function_per_window, objective_value(model))
+    for t in 1:move_forward
+        renewable_production[offset+t] = value(model[:r][t])
+        storage_level[offset+t] = value(model[:s][t])
+    end
 end
 
 # We can explore the outputs in the following graphs:
 
 Plots.plot(
-    objective_function_per_window;
+    objective_function_per_window ./ 10^3;
     label = false,
     linewidth = 3,
     xlabel = "Window",
-    ylabel = "\$",
-    title = "Objective Function per Window",
+    ylabel = "[000'] \$",
 )
 
 #-
@@ -322,6 +260,7 @@ Plots.plot(
     linewidth = 3,
     xlabel = "Hours",
     ylabel = "MW",
+    xticks = 0:12:total_time_length,
 )
 
 # **Final remark**: [ParametricOptInterface.jl](@ref) offers an easy way to