discrete.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. """Discrete solution classes implementations
  2. """
  3. import numpy as np
  4. # modules imports
  5. from macop.solutions.base import Solution
  6. class BinarySolution(Solution):
  7. """
  8. Binary integer solution class
  9. - store solution as a binary array (example: [0, 1, 0, 1, 1])
  10. - associated size is the size of the array
  11. - mainly use for selecting or not an element in a list of valuable objects
  12. Attributes:
  13. data: {ndarray} -- array of binary values
  14. size: {int} -- size of binary array values
  15. score: {float} -- fitness score value
  16. """
  17. def __init__(self, data, size):
  18. """
  19. initialise binary solution using specific data
  20. Args:
  21. data: {ndarray} -- array of binary values
  22. size: {int} -- size of binary array values
  23. Example:
  24. >>> from macop.solutions.discrete import BinarySolution
  25. >>>
  26. >>> # build of a solution using specific data and size
  27. >>> data = [0, 1, 0, 1, 1]
  28. >>> solution = BinarySolution(data, len(data))
  29. >>>
  30. >>> # check data content
  31. >>> sum(solution.data) == 3
  32. True
  33. >>> # clone solution
  34. >>> solution_copy = solution.clone()
  35. >>> all(solution_copy.data == solution.data)
  36. True
  37. """
  38. super().__init__(np.array(data), size)
  39. @staticmethod
  40. def random(size, validator=None):
  41. """
  42. Intialize binary array with use of validator to generate valid random solution
  43. Args:
  44. size: {int} -- expected solution size to generate
  45. validator: {function} -- specific function which validates or not a solution (if None, not validation is applied)
  46. Returns:
  47. {:class:`~macop.solutions.discrete.BinarySolution`}: new generated binary solution
  48. Example:
  49. >>> from macop.solutions.discrete import BinarySolution
  50. >>>
  51. >>> # generate random solution using specific validator
  52. >>> validator = lambda solution: True if sum(solution.data) > 5 else False
  53. >>> solution = BinarySolution.random(10, validator)
  54. >>> sum(solution.data) > 5
  55. True
  56. """
  57. data = np.random.randint(2, size=size)
  58. solution = BinarySolution(data, size)
  59. if not validator:
  60. return solution
  61. while not validator(solution):
  62. data = np.random.randint(2, size=size)
  63. solution = BinarySolution(data, size)
  64. return solution
  65. def __str__(self):
  66. return f"Binary solution {self._data}"
  67. class CombinatoryIntegerSolution(Solution):
  68. """
  69. Combinatory integer solution class
  70. - store solution as a combinatory array (example: [1, 3, 0, 2])
  71. - associated size is the size of the array
  72. - mainly use for selecting or not an element in a list of valuable objects
  73. Attributes:
  74. data: {ndarray} -- array of integer values
  75. size: {int} -- size of integer array values
  76. score: {float} -- fitness score value
  77. """
  78. def __init__(self, data, size):
  79. """
  80. initialise integer solution using specific data
  81. Args:
  82. data: {ndarray} -- array of integer values
  83. size: {int} -- size of integer array values
  84. >>> from macop.solutions.discrete import CombinatoryIntegerSolution
  85. >>> import numpy as np
  86. >>> data = np.arange(5)
  87. >>> solution = CombinatoryIntegerSolution(data, 5)
  88. >>> sum(solution.data) == 10
  89. True
  90. >>> solution_copy = solution.clone()
  91. >>> all(solution_copy.data == solution.data)
  92. True
  93. """
  94. super().__init__(data, size)
  95. @staticmethod
  96. def random(size, validator=None):
  97. """
  98. Intialize combinatory integer array with use of validator to generate valid random solution
  99. Args:
  100. size: {int} -- expected solution size to generate
  101. validator: {function} -- specific function which validates or not a solution (if None, not validation is applied)
  102. Returns:
  103. {:class:`~macop.solutions.discrete.CombinatoryIntegerSolution`}: new generated combinatory integer solution
  104. Example:
  105. >>> from macop.solutions.discrete import CombinatoryIntegerSolution
  106. >>>
  107. >>> # generate random solution using specific validator
  108. >>> validator = lambda solution: True if sum(solution.data) > 5 else False
  109. >>> solution = CombinatoryIntegerSolution.random(5, validator)
  110. >>> sum(solution.data) > 5
  111. True
  112. """
  113. data = np.arange(size)
  114. np.random.shuffle(data)
  115. solution = CombinatoryIntegerSolution(data, size)
  116. if not validator:
  117. return solution
  118. while not validator(solution):
  119. data = np.arange(size)
  120. np.random.shuffle(data)
  121. solution = CombinatoryIntegerSolution(data, size)
  122. return solution
  123. def __str__(self):
  124. return f"Combinatory integer solution {self._data}"
  125. class IntegerSolution(Solution):
  126. """
  127. Integer solution class
  128. Attributes:
  129. data: {ndarray} -- array of binary values
  130. size: {int} -- size of binary array values
  131. score: {float} -- fitness score value
  132. """
  133. def __init__(self, data, size):
  134. """
  135. initialise integer solution using specific data
  136. Args:
  137. data: {ndarray} -- array of binary values
  138. size: {int} -- size of binary array values
  139. Example:
  140. >>> from macop.solutions.discrete import IntegerSolution
  141. >>> import numpy as np
  142. >>> np.random.seed(42)
  143. >>> data = np.random.randint(5, size=10)
  144. >>> solution = IntegerSolution(data, 10)
  145. >>> sum(solution.data)
  146. 28
  147. >>> solution_copy = solution.clone()
  148. >>> all(solution_copy.data == solution.data)
  149. True
  150. """
  151. super().__init__(data, size)
  152. @staticmethod
  153. def random(size, validator=None):
  154. """
  155. Intialize integer array with use of validator to generate valid random solution
  156. Args:
  157. size: {int} -- expected solution size to generate
  158. validator: {function} -- specific function which validates or not a solution (if None, not validation is applied)
  159. Returns:
  160. {:class:`~macop.solutions.discrete.IntegerSolution`}: new generated integer solution
  161. Example:
  162. >>> from macop.solutions.discrete import IntegerSolution
  163. >>> import numpy as np
  164. >>> np.random.seed(42)
  165. >>>
  166. >>> # generate random solution using specific validator
  167. >>> validator = lambda solution: True if sum(solution.data) > 5 else False
  168. >>> solution = IntegerSolution.random(5, validator)
  169. >>> sum(solution.data) > 10
  170. True
  171. """
  172. data = np.random.randint(size, size=size)
  173. solution = IntegerSolution(data, size)
  174. if not validator:
  175. return solution
  176. while not validator(solution):
  177. data = np.random.randint(size, size=size)
  178. solution = IntegerSolution(data, size)
  179. return solution
  180. def __str__(self):
  181. return f"Integer solution {self._data}"