Algorithm.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. # main imports
  2. import logging
  3. # Generic algorithm class
  4. class Algorithm():
  5. def __init__(self,
  6. _initalizer,
  7. _evaluator,
  8. _operators,
  9. _policy,
  10. _validator,
  11. _maximise=True,
  12. _parent=None):
  13. """
  14. Initialize all usefull parameters for problem to solve
  15. """
  16. self.initializer = _initalizer
  17. self.evaluator = _evaluator
  18. self.operators = _operators
  19. self.validator = _validator
  20. self.policy = _policy
  21. self.checkpoint = None
  22. self.bestSolution = None
  23. # other parameters
  24. self.parent = _parent # parent algorithm if it's sub algorithm
  25. #self.maxEvaluations = 0 # by default
  26. self.maximise = _maximise
  27. self.initRun()
  28. def addCheckpoint(self, _class, _every, _filepath):
  29. self.checkpoint = _class(self, _every, _filepath)
  30. def setCheckpoint(self, _checkpoint):
  31. self.checkpoint = _checkpoint
  32. def resume(self):
  33. if self.checkpoint is None:
  34. raise ValueError(
  35. "Need to `addCheckpoint` or `setCheckpoint` is you want to use this process"
  36. )
  37. else:
  38. print('Checkpoint loading is called')
  39. self.checkpoint.load()
  40. def initRun(self):
  41. """
  42. Reinit the whole variables
  43. """
  44. # add track reference of algo into operator (keep an eye into best solution)
  45. for operator in self.operators:
  46. operator.setAlgo(self)
  47. self.currentSolution = self.initializer()
  48. # evaluate current solution
  49. self.currentSolution.evaluate(self.evaluator)
  50. # keep in memory best known solution (current solution)
  51. self.bestSolution = self.currentSolution
  52. def increaseEvaluation(self):
  53. self.numberOfEvaluations += 1
  54. if self.parent is not None:
  55. self.parent.numberOfEvaluations += 1
  56. def getGlobalEvaluation(self):
  57. if self.parent is not None:
  58. return self.parent.numberOfEvaluations
  59. return self.numberOfEvaluations
  60. def stop(self):
  61. """
  62. Global stopping criteria (check for inner algorithm too)
  63. """
  64. if self.parent is not None:
  65. return self.parent.numberOfEvaluations >= self.parent.maxEvaluations or self.numberOfEvaluations >= self.maxEvaluations
  66. return self.numberOfEvaluations >= self.maxEvaluations
  67. def evaluate(self, solution):
  68. """
  69. Returns:
  70. fitness score of solution which is not already evaluated or changed
  71. Note:
  72. if multi-objective problem this method can be updated using array of `evaluator`
  73. """
  74. return solution.evaluate(self.evaluator)
  75. def update(self, solution):
  76. """
  77. Apply update function to solution using specific `policy`
  78. Check if solution is valid after modification and returns it
  79. Returns:
  80. updated solution
  81. """
  82. # two parameters are sent if specific crossover solution are wished
  83. sol = self.policy.apply(solution)
  84. if (sol.isValid(self.validator)):
  85. return sol
  86. else:
  87. logging.info("-- New solution is not valid %s" % sol)
  88. return solution
  89. def isBetter(self, solution):
  90. """
  91. Check if solution is better than best found
  92. Returns:
  93. `True` if better
  94. """
  95. # depending of problem to solve (maximizing or minimizing)
  96. if self.maximise:
  97. if self.evaluate(solution) > self.bestSolution.fitness():
  98. return True
  99. else:
  100. if self.evaluate(solution) < self.bestSolution.fitness():
  101. return True
  102. # by default
  103. return False
  104. def run(self, _evaluations):
  105. """
  106. Run the specific algorithm following number of evaluations to find optima
  107. """
  108. self.maxEvaluations = _evaluations
  109. self.initRun()
  110. # check if global evaluation is used or not
  111. if self.parent is not None and self.getGlobalEvaluation() != 0:
  112. # init number evaluations of inner algorithm depending of globalEvaluation
  113. # allows to restart from `checkpoint` last evaluation into inner algorithm
  114. rest = self.getGlobalEvaluation() % self.maxEvaluations
  115. self.numberOfEvaluations = rest
  116. else:
  117. self.numberOfEvaluations = 0
  118. logging.info("Run %s with %s evaluations" %
  119. (self.__str__(), _evaluations))
  120. def progress(self):
  121. if self.checkpoint is not None:
  122. self.checkpoint.run()
  123. logging.info("-- %s evaluation %s of %s (%s%%) - BEST SCORE %s" %
  124. (type(self).__name__, self.numberOfEvaluations,
  125. self.maxEvaluations, "{0:.2f}".format(
  126. (self.numberOfEvaluations) / self.maxEvaluations *
  127. 100.), self.bestSolution.fitness()))
  128. def information(self):
  129. logging.info("-- Best %s - SCORE %s" %
  130. (self.bestSolution, self.bestSolution.fitness()))
  131. def __str__(self):
  132. return "%s using %s" % (type(self).__name__, type(
  133. self.bestSolution).__name__)