discrete.py 6.8 KB

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