Skip to content

Commit

Permalink
Add stochastic lead times example to docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Thuener authored Nov 5, 2024
1 parent b4c0a25 commit a120b60
Showing 1 changed file with 76 additions and 1 deletion.
77 changes: 76 additions & 1 deletion docs/src/guides/access_previous_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ end

## Access a decision from N stages ago

This is often useful if have some inventory problem with a lead-time on orders.
This is often useful if you have some inventory problem with a lead time on orders.
In the code below, we assume that the product has a lead time of 5 stages, and we
use a state variable to track the decisions on the production for the last 5 stages.
The decisions are passed to the next stage by shifting them by one stage.

```@repl
using SDDP, HiGHS
Expand Down Expand Up @@ -90,3 +93,75 @@ end
!!! warning
You must initialize the same number of state variables in every stage, even
if they are not used in that stage.

## Variable lead times

What do you do when the lead times are a stochastic variable?

In this example, we consider the lead time to follow a truncated Geometric
distribution.

### Tracking the orders
We add a dimension on the x_orders variable to track the orders in transit, assuming

Check failure on line 105 in docs/src/guides/access_previous_variables.md

View workflow job for this annotation

GitHub Actions / build

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'x_orders'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'x_orders'?", "location": {"path": "docs/src/guides/access_previous_variables.md", "range": {"start": {"line": 105, "column": 27}}}, "severity": "ERROR"}
they can take 1:T lead times. Thus, x_orders[1] are arriving in the inventory and
x_orders[2] will arrive in the next stage.

### Lead times as stochastic variable
The second trick here is to use ``\omega`` as a stochastic variable to represent the lead
together with set_normalized_coefficient to enable u_buy on the ``\omega`` is equal to i

Check failure on line 111 in docs/src/guides/access_previous_variables.md

View workflow job for this annotation

GitHub Actions / build

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'set_normalized_coefficient'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'set_normalized_coefficient'?", "location": {"path": "docs/src/guides/access_previous_variables.md", "range": {"start": {"line": 111, "column": 15}}}, "severity": "ERROR"}

Check failure on line 111 in docs/src/guides/access_previous_variables.md

View workflow job for this annotation

GitHub Actions / build

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'u_buy'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'u_buy'?", "location": {"path": "docs/src/guides/access_previous_variables.md", "range": {"start": {"line": 111, "column": 52}}}, "severity": "ERROR"}
and disable to the rest. For example, if ``\omega`` = 2, it means that it will take 2 stages
for the order to arrive. In this case, we will have (for `T` =4):
```julia
c_orders[1], x_orders[2].in + 0 * u_buy == x_orders[1].out
c_orders[2], x_orders[3].in + 1 * u_buy == x_orders[2].out
c_orders[3], x_orders[4].in + 0 * u_buy == x_orders[3].out
c_orders[4], x_orders[5].in + 0 * u_buy == x_orders[4].out
```
Let us take a look at c_orders[2]. Decision variable x_orders[2].out will receive
the orders that were already placed and will arrive in 3 stages x_orders[3].in
plus u_buy. In the next stage, this order will pushed to x_orders[1].out and, in

Check failure on line 122 in docs/src/guides/access_previous_variables.md

View workflow job for this annotation

GitHub Actions / build

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'u_buy'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'u_buy'?", "location": {"path": "docs/src/guides/access_previous_variables.md", "range": {"start": {"line": 122, "column": 6}}}, "severity": "ERROR"}
the following stage, to x_orders[1].in and into the inventory.

```@repl
using SDDP
import HiGHS
import Distributions
T = 10
model = SDDP.LinearPolicyGraph(
stages = 20,
sense = :Max,
upper_bound = 1000,
optimizer = HiGHS.Optimizer,
) do sp, t
@variables(sp, begin
x_inventory >= 0, SDDP.State, (initial_value = 0)
# Add an extra dimention on the orders to track the orders lead times
x_orders[1:T+1], SDDP.State, (initial_value = 0)
0 <= u_buy <= 10
u_sell >= 0
end)
fix(x_orders[T+1].out, 0)
@stageobjective(sp, u_sell)
@constraints(sp, begin
# Shift the orders one stage
c_orders[i=1:T], x_orders[i+1].in + 1 * u_buy == x_orders[i].out
# x_orders[1].in are arriving on the inventory
x_inventory.out == x_inventory.in - u_sell + x_orders[1].in
end)
#
Ω = 1:T
P = Distributions.pdf.(Distributions.Geometric(1 / 5), 0:T-1)
P ./= sum(P)
SDDP.parameterize(sp, Ω, P) do ω
# Rewrite the constraint c_orders[i=1:T] indicating how many stages
# ahead the order will arrive (ω)
# x_orders[i+1].in + 1 * u_buy == x_orders[i].out
# if ω == i and
# x_orders[i+1].in + 0 * u_buy == x_orders[i].out
# if ω != i.
for i in Ω
set_normalized_coefficient(c_orders[i], u_buy, ω == i ? 1 : 0)
end
end
end
```

0 comments on commit a120b60

Please sign in to comment.