Algorithm.py 4.8 KB

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