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

1""" 

2Maximize the worst-case immediate rate. 

3 

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. 

10 

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". 

15 

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""" 

27 

28 

29from moptipy.api.objective import Objective 

30 

31from moptipyapps.prodsched.multistatistics import MultiStatistics 

32 

33 

34class WorstFillRate(Objective): 

35 """Compute the worst immediate rate and return `1 -` of it.""" 

36 

37 def evaluate(self, x: MultiStatistics) -> int | float: 

38 """ 

39 Get the negated worst immediate rate. 

40 

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 

51 

52 def lower_bound(self) -> int: 

53 """ 

54 Get the lower bound of the inverted minimum immediate rate. 

55 

56 :retval 0: always 

57 """ 

58 return 0 

59 

60 def upper_bound(self) -> int: 

61 """ 

62 Get the upper bound of the inverted minimum immediate rate. 

63 

64 :retval 1: always 

65 """ 

66 return 1 

67 

68 def __str__(self) -> str: 

69 """ 

70 Get the name of the objective function. 

71 

72 :return: `worstFillRate` 

73 :retval "worstFillRate": always 

74 """ 

75 return "worstFillRate"