Skip to content

feat: Implement replenishment benchmark - #96

Open
NicolasCorvol wants to merge 20 commits into
mainfrom
replenishment_benchmark
Open

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

Conversation

@NicolasCorvol

Copy link
Copy Markdown
Contributor

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 3 times, most recently 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

Codecov Report

❌ Patch coverage is 87.17633% with 104 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/DynamicReplenishment/policies.jl 60.00% 52 Missing ⚠️
ext/plots/dynamic_replenishment_plots.jl 58.00% 21 Missing ⚠️
src/DynamicReplenishment/DynamicReplenishment.jl 87.91% 11 Missing ⚠️
src/DynamicReplenishment/environment.jl 83.33% 8 Missing ⚠️
src/DynamicReplenishment/state.jl 96.42% 4 Missing ⚠️
src/DynamicReplenishment/anticipative_solver.jl 98.87% 2 Missing ⚠️
src/DynamicReplenishment/features.jl 98.16% 2 Missing ⚠️
src/DynamicReplenishment/utils.jl 33.33% 2 Missing ⚠️
src/Utils/interface/dynamic_benchmark.jl 0.00% 2 Missing ⚠️
Files with missing lines Coverage Δ
ext/DFLBenchmarksPlotsExt.jl 100.00% <ø> (ø)
src/DecisionFocusedLearningBenchmarks.jl 100.00% <ø> (ø)
src/DynamicReplenishment/maximizer.jl 100.00% <100.00%> (ø)
src/DynamicReplenishment/scenario.jl 100.00% <100.00%> (ø)
src/DynamicReplenishment/statistical_model.jl 100.00% <100.00%> (ø)
src/Utils/Utils.jl 100.00% <ø> (ø)
src/Utils/model_builders.jl 100.00% <100.00%> (ø)
src/DynamicReplenishment/anticipative_solver.jl 98.87% <98.87%> (ø)
src/DynamicReplenishment/features.jl 98.16% <98.16%> (ø)
src/DynamicReplenishment/utils.jl 33.33% <33.33%> (ø)
... and 6 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@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
Comment thread src/DynamicReplenishment/state.jl
@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
Contributor 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
Comment thread src/DynamicReplenishment/policies.jl Outdated

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.

issue: the quotas matrix needs to be sliced to start at the current time step, in the same way it is done in the anticipative solver

virtual_stock_cost = prices ./ (max_steps * 10)
physical_stock_cost = prices ./ (max_steps * 5)
over_stock_bound_cost = maximum(prices)
max_quotas = Matrix{Float64}(undef, max_steps, N)

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.

issue: max_quotas is defined as Matrix{Int} in the struct definition, but initialized as Matrix{Float64} here

@NicolasCorvol
NicolasCorvol force-pushed the replenishment_benchmark branch from 8b67eb5 to 960acd6 Compare August 7, 2026 13:22
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