Coverage for moptipyapps / binpacking2d / objectives / bin_count.py: 96%

24 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 04:40 +0000

1""" 

2An objective function for minimizing the number of bins in packings. 

3 

4This function returns the number of bins. 

5""" 

6from typing import Final 

7 

8from moptipy.api.objective import Objective 

9from pycommons.types import type_error 

10 

11from moptipyapps.binpacking2d.instance import Instance 

12from moptipyapps.binpacking2d.packing import IDX_BIN 

13 

14#: the name of the bin count objective function 

15BIN_COUNT_NAME: Final[str] = "binCount" 

16 

17 

18class BinCount(Objective): 

19 """Compute the number of bins.""" 

20 

21 def __init__(self, instance: Instance) -> None: 

22 """ 

23 Initialize the number of bins objective function. 

24 

25 :param instance: the instance to load the bounds from 

26 """ 

27 super().__init__() 

28 if not isinstance(instance, Instance): 

29 raise type_error(instance, "instance", Instance) 

30 #: the internal instance reference 

31 self._instance: Final[Instance] = instance 

32 

33 def evaluate(self, x) -> int: 

34 """ 

35 Get the number of bins. 

36 

37 :param x: the packing 

38 :return: the number of bins used 

39 """ 

40 return int(x[:, IDX_BIN].max()) 

41 

42 def lower_bound(self) -> int: 

43 """ 

44 Get the lower bound of the number of bins objective. 

45 

46 :return: the lower bound for the number of required bins, i.e., 

47 :attr:`~moptipyapps.binpacking2d.instance.Instance.\ 

48lower_bound_bins` 

49 

50 >>> ins = Instance("a", 100, 50, [[10, 5, 1], [3, 3, 1], [5, 5, 1]]) 

51 >>> ins.lower_bound_bins 

52 1 

53 >>> BinCount(ins).lower_bound() 

54 1 

55 

56 >>> ins = Instance("b", 10, 50, [[10, 5, 10], [3, 3, 1], [5, 5, 1]]) 

57 >>> ins.lower_bound_bins 

58 2 

59 >>> BinCount(ins).lower_bound() 

60 2 

61 

62 >>> ins = Instance("c", 10, 50, [[10, 5, 20], [30, 3, 10], [5, 5, 1]]) 

63 >>> ins.lower_bound_bins 

64 4 

65 >>> BinCount(ins).lower_bound() 

66 4 

67 """ 

68 return self._instance.lower_bound_bins 

69 

70 def is_always_integer(self) -> bool: 

71 """ 

72 Return `True` because there are only integer bins. 

73 

74 :retval True: always 

75 """ 

76 return True 

77 

78 def upper_bound(self) -> int: 

79 """ 

80 Get the upper bound of the number of bins. 

81 

82 :return: the number of items in the instance, i.e., 

83 :attr:`~moptipyapps.binpacking2d.instance.Instance.n_items` 

84 

85 >>> ins = Instance("a", 100, 50, [[10, 5, 1], [3, 3, 1], [5, 5, 1]]) 

86 >>> ins.n_items 

87 3 

88 >>> BinCount(ins).upper_bound() 

89 3 

90 

91 >>> ins = Instance("b", 10, 50, [[10, 5, 10], [3, 3, 1], [5, 5, 1]]) 

92 >>> ins.n_items 

93 12 

94 >>> BinCount(ins).upper_bound() 

95 12 

96 

97 >>> ins = Instance("c", 10, 50, [[10, 5, 20], [30, 3, 10], [5, 5, 1]]) 

98 >>> ins.n_items 

99 31 

100 >>> BinCount(ins).upper_bound() 

101 31 

102 """ 

103 return self._instance.n_items 

104 

105 def to_bin_count(self, z: int) -> int: 

106 """ 

107 Get the bin count corresponding to an objective value. 

108 

109 :param z: 

110 :return: the value itself 

111 """ 

112 return z 

113 

114 def __str__(self) -> str: 

115 """ 

116 Get the name of the bins objective function. 

117 

118 :return: `binCount` 

119 :retval "binCount": always 

120 """ 

121 return BIN_COUNT_NAME