ソースを参照

First checkpoint version

Jérôme BUISINE 4 年 前
コミット
690f1a0e3b

+ 38 - 1
algorithms/Algorithm.py

@@ -4,7 +4,7 @@ import logging
 # Generic algorithm class
 class Algorithm():
 
-    def __init__(self, _initalizer, _evaluator, _operators, _policy, _validator, _maximise=True):
+    def __init__(self, _initalizer, _evaluator, _operators, _policy, _validator, _maximise=True, _parent=None):
         """
         Initialize all usefull parameters for problem to solve
         """
@@ -14,14 +14,32 @@ class Algorithm():
         self.operators = _operators
         self.validator = _validator
         self.policy = _policy
+        self.checkpoint = None
 
         # other parameters
+        self.parent = _parent # parent algorithm if it's sub algorithm
         self.maxEvalutations = 0 # by default
         self.maximise = _maximise
 
         self.initRun()
 
 
+    def addCheckpoint(self, _class, _every, _filepath):
+        self.checkpoint = _class(self, _every, _filepath)
+
+    
+    def setCheckpoint(self, _checkpoint):
+        self.checkpoint = _checkpoint
+
+
+    def resume(self):
+        if self.checkpoint is None:
+            raise ValueError("Need to `addCheckpoint` or `setCheckpoint` is you want to use this process")
+        else:
+            print('Checkpoint loading is called')
+            self.checkpoint.load()
+
+
     def initRun(self):
         """
         Reinit the whole variables
@@ -38,6 +56,21 @@ class Algorithm():
         self.numberOfEvaluations = 0
 
 
+    def increaseEvaluation(self):
+        self.numberOfEvaluations += 1
+
+        if self.parent is not None:
+            self.parent.numberOfEvaluations += 1
+
+    
+    def getGlobalEvaluation(self):
+
+        if self.parent is not None:
+            return self.parent.numberOfEvaluations
+
+        return self.numberOfEvaluations
+
+
     def evaluate(self, solution):
         """
         Returns: 
@@ -99,6 +132,10 @@ class Algorithm():
 
 
     def progress(self):
+
+        if self.checkpoint is not None:
+            self.checkpoint.run()
+
         logging.info("-- %s evaluation %s of %s (%s%%) - BEST SCORE %s" % (type(self).__name__, self.numberOfEvaluations, self.maxEvalutations, "{0:.2f}".format((self.numberOfEvaluations) / self.maxEvalutations * 100.), self.bestSolution.fitness()))
 
 

+ 16 - 6
algorithms/IteratedLocalSearch.py

@@ -12,10 +12,19 @@ class IteratedLocalSearch(Algorithm):
         # by default use of mother method to initialize variables
         super().run(_evaluations)
 
-        ls = LocalSearch(self.initializer, self.evaluator, self.operators, self.policy, self.validator, self.maximise)
+        # enable checkpoint for ILS
+        if self.checkpoint is not None:
+            self.resume()
+
+        # passing global evaluation param from ILS
+        ls = LocalSearch(self.initializer, self.evaluator, self.operators, self.policy, self.validator, self.maximise, _parent=self)
+        
+        # set same checkpoint if exists
+        if self.checkpoint is not None:
+            ls.setCheckpoint(self.checkpoint)
 
         # local search algorithm implementation
-        while self.numberOfEvaluations < self.maxEvalutations:
+        while self.getGlobalEvaluation() < self.maxEvalutations:
             
             # create and search solution from local search
             newSolution = ls.run(_ls_evaluations)
@@ -24,11 +33,12 @@ class IteratedLocalSearch(Algorithm):
             if self.isBetter(newSolution):
                 self.bestSolution = newSolution
 
-            # increase number of evaluations
-            self.numberOfEvaluations += _ls_evaluations
+            # number of evaluatins increased from LocalSearch
+            # increase number of evaluations and progress are then not necessary there
+            #self.increaseEvaluation()
+            #self.progress()
 
-            self.progress()
-            self.information()            
+            self.information()          
 
         logging.info("End of %s, best solution found %s" % (type(self).__name__, self.bestSolution))
 

+ 2 - 2
algorithms/LocalSearch.py

@@ -14,7 +14,7 @@ class LocalSearch(Algorithm):
         solutionSize = self.bestSolution.size
 
         # local search algorithm implementation
-        while self.numberOfEvaluations < self.maxEvalutations:
+        while self.getGlobalEvaluation() < self.maxEvalutations:
 
             for _ in range(solutionSize):
 
@@ -27,7 +27,7 @@ class LocalSearch(Algorithm):
                     self.bestSolution = newSolution
 
                 # increase number of evaluations
-                self.numberOfEvaluations += 1
+                self.increaseEvaluation()
 
                 self.progress()
                 logging.info("---- Current %s - SCORE %s" % (newSolution, newSolution.fitness()))

+ 69 - 0
checkpoints/BasicCheckpoint.py

@@ -0,0 +1,69 @@
+# main imports
+import os
+import logging
+
+# module imports
+from .Checkpoint import Checkpoint
+
+class BasicCheckpoint(Checkpoint):
+
+    def __init__(self, _algo, _every, _filepath):
+        self.algo = _algo
+        self.every = _every
+        self.filepath = _filepath
+
+
+    def run(self):
+
+        # get current best solution
+        solution = self.algo.bestSolution
+
+        currentEvaluation = self.algo.getGlobalEvaluation()
+
+        # backup if necessary
+        if currentEvaluation % self.every == 0:
+
+            logging.info("Checkpoint is done into " + self.filepath)
+
+            cleanSolution =  str(solution.data).replace('[', '').replace(']', '')
+            line = str(currentEvaluation) + ';' + cleanSolution + ';' + str(solution.fitness()) + ';\n'
+
+            # check if file exists
+            if not os.path.exists(self.filepath):
+                with open(self.filepath, 'w') as f:
+                    f.write(line)
+            else:
+                with open(self.filepath, 'a') as f:
+                    f.write(line)
+
+
+    def load(self):
+
+        if os.path.exists(self.filepath):
+
+            logging.info('Load best solution from last checkpoint')
+            with open(self.filepath) as f:
+
+                # get last line and read data
+                lastline = f.readlines()[-1]
+                data = lastline.split(';')
+                
+                # get evaluation  information 
+                globalEvaluation = int(data[0])
+
+                print(globalEvaluation, data)
+
+                if self.algo.parent is not None:
+                    self.algo.parent.numberOfEvaluations = globalEvaluation
+                else:
+                    self.algo.numberOfEvaluations = globalEvaluation
+
+                print(self.algo.numberOfEvaluations)
+                # get best solution data information
+                solutionData = list(map(int, data[1].split(' ')))
+
+                print(solutionData)
+                self.algo.bestSolution.data = solutionData
+                self.algo.bestSolution.score = float(data[2])
+        else:
+            logging.info("Can't load backup... Backup filepath not valid in Checkpoint")

+ 22 - 0
checkpoints/Checkpoint.py

@@ -0,0 +1,22 @@
+# main imports
+import os
+import logging
+
+class Checkpoint():
+
+    def __init__(self, _algo, _every, _filepath):
+        self.algo = _algo
+        self.every = _every
+        self.filepath = _filepath
+
+    def run(self):
+        """
+        Check if necessary to do backup based on `_every` variable
+        """
+        pass
+
+    def load(self):
+        """
+        Load last backup line of solution and set algorithm state at this backup
+        """
+        pass

+ 0 - 0
checkpoints/__init__.py