Skip to content

feat: Implement replenishment benchmark - #96

Open
NicolasCorvol wants to merge 15 commits into
mainfrom
replenishment_benchmark
Open

feat: Implement replenishment benchmark#96
NicolasCorvol wants to merge 15 commits into
mainfrom
replenishment_benchmark

Conversation

@NicolasCorvol

Copy link
Copy Markdown

This Pull Request adds the dynamic replenishment benchmark to the list of available benchmarks.

@NicolasCorvol NicolasCorvol self-assigned this Jul 2, 2026
@NicolasCorvol
NicolasCorvol requested a review from BatyLeo July 2, 2026 16:57
@NicolasCorvol
NicolasCorvol force-pushed the replenishment_benchmark branch from 6d46b59 to b0ef349 Compare July 3, 2026 07:23
@NicolasCorvol
NicolasCorvol force-pushed the replenishment_benchmark branch from 8058990 to bb9c34a Compare July 3, 2026 18:55
@NicolasCorvol
NicolasCorvol force-pushed the replenishment_benchmark branch from 40b64d9 to f13f6cd Compare July 7, 2026 16:26
@BatyLeo BatyLeo added the enhancement New feature or request label Jul 9, 2026
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

@BatyLeo BatyLeo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your huge (you were probably right and we should have cut it in multiple smaller PRs) contribution, good start!
I've reviewed most of the src code (I just have not yet checked the maths of the maximizer and of the anticipative solver). I'll review what is missing along with plot utilities and tests in a second wave.

There are some bugs scattered around (see comments) to correct and some things to cleanup (add a bit more doctrings and explanation of what core methods/types do).
Additionally, it would be nice to have a documentation page describing the maths (see other benchmark pages) of this problem (it's quite difficult to understand the details and design choices by only reading the code).

Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/maximizer.jl Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/utils.jl Outdated
Comment thread src/DynamicReplenishment/utils.jl Outdated
Comment thread src/DynamicReplenishment/scenario.jl Outdated
@BatyLeo BatyLeo changed the title add replenishment benchmark feat: Implement replenishment benchmark Jul 24, 2026

@BatyLeo BatyLeo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second round of review:

  • reviewed the new changes
  • reviewed the anticipative and maximizer
  • still need to review tests and plots

Comment thread docs/src/api.md Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
Comment thread src/DynamicReplenishment/DynamicReplenishment.jl Outdated
scenario::Scenario
"initial stock"
stock_ini::Vector{Int}
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the stock is mutated in place the struct is still non-mutable since we do not overwrite its value (only its content)

Comment thread src/DynamicReplenishment/policies.jl Outdated
Comment thread src/DynamicReplenishment/anticipative_solver.jl Outdated
Comment thread src/DynamicReplenishment/anticipative_solver.jl Outdated
"""
mutable struct DRPState{B<:DynamicReplenishmentBenchmark}
"The benchmark configuration."
config::B

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: do we absolutely need to store the benchmark in state? This can affect performance when using deepcopy

@NicolasCorvol NicolasCorvol Jul 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the benchmark for the maximizer : we need the constraint matrix, the number of items....
One thing that we could do is override the deepcopy of the states in order to not copying the benchmark.
We have this performance:

julia> @allocated deepcopy(state)
7568
julia> @elapsed for _ in 1:2000 deepcopy(state) end
0.003458666
julia> @allocated deepcopy(state.config)
525360
julia> @elapsed for _ in 1:2000 deepcopy(state.config) end
0.060429333

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the changes have been made in 16dadd0

@constraint(
m,
[i in 1:N, t in 2:(T + 1)],
v[t, i] >=

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I'm not sure to understand this constraint. When z[i, t] == 0, this means 0 >= v[t, i] >= this. What am I missing?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The physical stock is defined as the number of items that arrived in the store ( > delivery_delay time steps) and are not yet sold.

The number of items that have arrived in t in the store is :
arrived_t = stock_ini[i] + sum(y[τ, i] for τ in 1:(t - delivery_delay)

The number of items sold in t is :
sold = sum(α[i, τ, k] for τ in 1:(t - 1) for k in 1:nb_customers[τ])

Therefore, the physical stock is defined as :

max(0,  arrived - sold)

To linearize this, we have :

  1. v >= arrived - sold
  2. v <= arrived - sold + M * (1 - z)
  3. v <= M * z

Therefore :

  • if z=0 : necessary arrived-sold = 0 or constraint 1. is violated and we have 0 <= v <= 0
  • if z = 1 : arrived - sold >= 0 and v = arrived - sold

@NicolasCorvol
NicolasCorvol force-pushed the replenishment_benchmark branch from abd4455 to 16dadd0 Compare July 28, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants