|
@@ -1,10 +1,17 @@
|
|
# main imports
|
|
# main imports
|
|
import logging
|
|
import logging
|
|
|
|
|
|
|
|
+
|
|
# Generic algorithm class
|
|
# Generic algorithm class
|
|
class Algorithm():
|
|
class Algorithm():
|
|
-
|
|
|
|
- def __init__(self, _initalizer, _evaluator, _operators, _policy, _validator, _maximise=True, _parent=None):
|
|
|
|
|
|
+ def __init__(self,
|
|
|
|
+ _initalizer,
|
|
|
|
+ _evaluator,
|
|
|
|
+ _operators,
|
|
|
|
+ _policy,
|
|
|
|
+ _validator,
|
|
|
|
+ _maximise=True,
|
|
|
|
+ _parent=None):
|
|
"""
|
|
"""
|
|
Initialize all usefull parameters for problem to solve
|
|
Initialize all usefull parameters for problem to solve
|
|
"""
|
|
"""
|
|
@@ -15,44 +22,46 @@ class Algorithm():
|
|
self.validator = _validator
|
|
self.validator = _validator
|
|
self.policy = _policy
|
|
self.policy = _policy
|
|
self.checkpoint = None
|
|
self.checkpoint = None
|
|
|
|
+ self.bestSolution = None
|
|
|
|
|
|
# other parameters
|
|
# other parameters
|
|
- self.parent = _parent # parent algorithm if it's sub algorithm
|
|
|
|
|
|
+ self.parent = _parent # parent algorithm if it's sub algorithm
|
|
#self.maxEvaluations = 0 # by default
|
|
#self.maxEvaluations = 0 # by default
|
|
self.maximise = _maximise
|
|
self.maximise = _maximise
|
|
|
|
|
|
self.initRun()
|
|
self.initRun()
|
|
|
|
|
|
-
|
|
|
|
def addCheckpoint(self, _class, _every, _filepath):
|
|
def addCheckpoint(self, _class, _every, _filepath):
|
|
self.checkpoint = _class(self, _every, _filepath)
|
|
self.checkpoint = _class(self, _every, _filepath)
|
|
|
|
|
|
-
|
|
|
|
def setCheckpoint(self, _checkpoint):
|
|
def setCheckpoint(self, _checkpoint):
|
|
self.checkpoint = _checkpoint
|
|
self.checkpoint = _checkpoint
|
|
|
|
|
|
-
|
|
|
|
def resume(self):
|
|
def resume(self):
|
|
if self.checkpoint is None:
|
|
if self.checkpoint is None:
|
|
- raise ValueError("Need to `addCheckpoint` or `setCheckpoint` is you want to use this process")
|
|
|
|
|
|
+ raise ValueError(
|
|
|
|
+ "Need to `addCheckpoint` or `setCheckpoint` is you want to use this process"
|
|
|
|
+ )
|
|
else:
|
|
else:
|
|
print('Checkpoint loading is called')
|
|
print('Checkpoint loading is called')
|
|
self.checkpoint.load()
|
|
self.checkpoint.load()
|
|
|
|
|
|
-
|
|
|
|
def initRun(self):
|
|
def initRun(self):
|
|
"""
|
|
"""
|
|
Reinit the whole variables
|
|
Reinit the whole variables
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
+ # add track reference of algo into operator (keep an eye into best solution)
|
|
|
|
+ for operator in self.operators:
|
|
|
|
+ operator.setAlgo(self)
|
|
|
|
+
|
|
self.currentSolution = self.initializer()
|
|
self.currentSolution = self.initializer()
|
|
-
|
|
|
|
|
|
+
|
|
# evaluate current solution
|
|
# evaluate current solution
|
|
self.currentSolution.evaluate(self.evaluator)
|
|
self.currentSolution.evaluate(self.evaluator)
|
|
|
|
|
|
# keep in memory best known solution (current solution)
|
|
# keep in memory best known solution (current solution)
|
|
self.bestSolution = self.currentSolution
|
|
self.bestSolution = self.currentSolution
|
|
-
|
|
|
|
|
|
|
|
def increaseEvaluation(self):
|
|
def increaseEvaluation(self):
|
|
self.numberOfEvaluations += 1
|
|
self.numberOfEvaluations += 1
|
|
@@ -60,7 +69,6 @@ class Algorithm():
|
|
if self.parent is not None:
|
|
if self.parent is not None:
|
|
self.parent.numberOfEvaluations += 1
|
|
self.parent.numberOfEvaluations += 1
|
|
|
|
|
|
-
|
|
|
|
def getGlobalEvaluation(self):
|
|
def getGlobalEvaluation(self):
|
|
|
|
|
|
if self.parent is not None:
|
|
if self.parent is not None:
|
|
@@ -68,16 +76,14 @@ class Algorithm():
|
|
|
|
|
|
return self.numberOfEvaluations
|
|
return self.numberOfEvaluations
|
|
|
|
|
|
-
|
|
|
|
def stop(self):
|
|
def stop(self):
|
|
"""
|
|
"""
|
|
Global stopping criteria (check for inner algorithm too)
|
|
Global stopping criteria (check for inner algorithm too)
|
|
"""
|
|
"""
|
|
if self.parent is not None:
|
|
if self.parent is not None:
|
|
return self.parent.numberOfEvaluations >= self.parent.maxEvaluations or self.numberOfEvaluations >= self.maxEvaluations
|
|
return self.parent.numberOfEvaluations >= self.parent.maxEvaluations or self.numberOfEvaluations >= self.maxEvaluations
|
|
-
|
|
|
|
- return self.numberOfEvaluations >= self.maxEvaluations
|
|
|
|
|
|
|
|
|
|
+ return self.numberOfEvaluations >= self.maxEvaluations
|
|
|
|
|
|
def evaluate(self, solution):
|
|
def evaluate(self, solution):
|
|
"""
|
|
"""
|
|
@@ -89,8 +95,7 @@ class Algorithm():
|
|
"""
|
|
"""
|
|
return solution.evaluate(self.evaluator)
|
|
return solution.evaluate(self.evaluator)
|
|
|
|
|
|
-
|
|
|
|
- def update(self, solution, secondSolution=None):
|
|
|
|
|
|
+ def update(self, solution):
|
|
"""
|
|
"""
|
|
Apply update function to solution using specific `policy`
|
|
Apply update function to solution using specific `policy`
|
|
|
|
|
|
@@ -101,15 +106,14 @@ class Algorithm():
|
|
"""
|
|
"""
|
|
|
|
|
|
# two parameters are sent if specific crossover solution are wished
|
|
# two parameters are sent if specific crossover solution are wished
|
|
- sol = self.policy.apply(solution, secondSolution)
|
|
|
|
|
|
+ sol = self.policy.apply(solution)
|
|
|
|
|
|
- if(sol.isValid(self.validator)):
|
|
|
|
|
|
+ if (sol.isValid(self.validator)):
|
|
return sol
|
|
return sol
|
|
else:
|
|
else:
|
|
logging.info("-- New solution is not valid %s" % sol)
|
|
logging.info("-- New solution is not valid %s" % sol)
|
|
return solution
|
|
return solution
|
|
|
|
|
|
-
|
|
|
|
def isBetter(self, solution):
|
|
def isBetter(self, solution):
|
|
"""
|
|
"""
|
|
Check if solution is better than best found
|
|
Check if solution is better than best found
|
|
@@ -128,7 +132,6 @@ class Algorithm():
|
|
# by default
|
|
# by default
|
|
return False
|
|
return False
|
|
|
|
|
|
-
|
|
|
|
def run(self, _evaluations):
|
|
def run(self, _evaluations):
|
|
"""
|
|
"""
|
|
Run the specific algorithm following number of evaluations to find optima
|
|
Run the specific algorithm following number of evaluations to find optima
|
|
@@ -140,7 +143,7 @@ class Algorithm():
|
|
|
|
|
|
# check if global evaluation is used or not
|
|
# check if global evaluation is used or not
|
|
if self.parent is not None and self.getGlobalEvaluation() != 0:
|
|
if self.parent is not None and self.getGlobalEvaluation() != 0:
|
|
-
|
|
|
|
|
|
+
|
|
# init number evaluations of inner algorithm depending of globalEvaluation
|
|
# init number evaluations of inner algorithm depending of globalEvaluation
|
|
# allows to restart from `checkpoint` last evaluation into inner algorithm
|
|
# allows to restart from `checkpoint` last evaluation into inner algorithm
|
|
rest = self.getGlobalEvaluation() % self.maxEvaluations
|
|
rest = self.getGlobalEvaluation() % self.maxEvaluations
|
|
@@ -149,22 +152,24 @@ class Algorithm():
|
|
else:
|
|
else:
|
|
self.numberOfEvaluations = 0
|
|
self.numberOfEvaluations = 0
|
|
|
|
|
|
- logging.info("Run %s with %s evaluations" % (self.__str__(), _evaluations))
|
|
|
|
-
|
|
|
|
|
|
+ logging.info("Run %s with %s evaluations" %
|
|
|
|
+ (self.__str__(), _evaluations))
|
|
|
|
|
|
def progress(self):
|
|
def progress(self):
|
|
|
|
|
|
if self.checkpoint is not None:
|
|
if self.checkpoint is not None:
|
|
self.checkpoint.run()
|
|
self.checkpoint.run()
|
|
|
|
|
|
- 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()))
|
|
|
|
-
|
|
|
|
|
|
+ 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()))
|
|
|
|
|
|
def information(self):
|
|
def information(self):
|
|
- logging.info("-- Best %s - SCORE %s" % (self.bestSolution, self.bestSolution.fitness()))
|
|
|
|
-
|
|
|
|
|
|
+ logging.info("-- Best %s - SCORE %s" %
|
|
|
|
+ (self.bestSolution, self.bestSolution.fitness()))
|
|
|
|
|
|
def __str__(self):
|
|
def __str__(self):
|
|
- return "%s using %s" % (type(self).__name__, type(self.bestSolution).__name__)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ return "%s using %s" % (type(self).__name__, type(
|
|
|
|
+ self.bestSolution).__name__)
|