Coverage for moptipyapps / prodsched / objectives / worst_fill_rate.py: 41%
17 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-13 08:40 +0000
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-13 08:40 +0000
1"""
2Maximize the worst-case immediate rate.
4This objective function tries to find solutions which have very robust fill
5rates.
6The fill rate is the fraction of customers that can get served directly,
7i.e., the fraction of customers that do not need to wait.
8This means that it is the fraction of customers whose demands can directly be
9satisfied from the stock.
11Fill rates are between 0 and 1.
12Of course, high fill rates are good and should therefore be subject to
13maximization.
14However, since we can only *minimize*, we minimize "1 - fill rate".
16Now, the question is:
17What is a *robust* fill rate / solution?
18Well, we simulate the solutions (such as re-order points) over multiple
19instances.
20A robust good fill rate would be high on the worst instance.
21In other words, the smallest fill rate measured on any instance should
22be as high as possible.
23This means that the largest value "1 - fill rate" should be as small as
24possible.
25So we use this as result of our objective function.
26"""
29from moptipy.api.objective import Objective
31from moptipyapps.prodsched.multistatistics import MultiStatistics
34class WorstFillRate(Objective):
35 """Compute the worst immediate rate and return `1 -` of it."""
37 def evaluate(self, x: MultiStatistics) -> int | float:
38 """
39 Get the negated worst immediate rate.
41 :param x: the multi-statistics
42 :return: the worst stock level
43 """
44 min_imm: int | float = 1
45 for stat in x.per_instance:
46 for sl in stat.immediate_rates:
47 if (sl is None) or not (0 < sl <= 1):
48 return 1
49 min_imm = min(min_imm, sl)
50 return 1 - min_imm
52 def lower_bound(self) -> int:
53 """
54 Get the lower bound of the inverted minimum immediate rate.
56 :retval 0: always
57 """
58 return 0
60 def upper_bound(self) -> int:
61 """
62 Get the upper bound of the inverted minimum immediate rate.
64 :retval 1: always
65 """
66 return 1
68 def __str__(self) -> str:
69 """
70 Get the name of the objective function.
72 :return: `worstFillRate`
73 :retval "worstFillRate": always
74 """
75 return "worstFillRate"