Bladeren bron

update of documentation motivation

Jérôme BUISINE 4 jaren geleden
bovenliggende
commit
36c7bae7e4

+ 3 - 3
macop/algorithms/mono.py

@@ -45,7 +45,7 @@ class HillClimberFirstImprovment(Algorithm):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(problem_size) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation
@@ -148,7 +148,7 @@ class HillClimberBestImprovment(Algorithm):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(problem_size) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation
@@ -253,7 +253,7 @@ class IteratedLocalSearch(Algorithm):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(problem_size) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation

+ 2 - 2
macop/algorithms/multi.py

@@ -51,7 +51,7 @@ class MOEAD(Algorithm):
     >>> evaluator2 = KnapsackEvaluator(data={'worths': worths2})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(problem_size) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation
@@ -415,7 +415,7 @@ class MOSubProblem(Algorithm):
     >>> evaluator2 = KnapsackEvaluator(data={'worths': worths2})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(problem_size) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation

+ 3 - 3
macop/callbacks/classicals.py

@@ -35,9 +35,9 @@ class BasicCheckpoint(Callback):
             logging.info("Checkpoint is done into " + self._filepath)
 
             solutionData = ""
-            solutionSize = len(solution._data)
+            solutionSize = len(solution.getData())
 
-            for index, val in enumerate(solution._data):
+            for index, val in enumerate(solution.getData()):
                 solutionData += str(val)
 
                 if index < solutionSize - 1:
@@ -82,7 +82,7 @@ class BasicCheckpoint(Callback):
                 if self._algo._bestSolution is None:
                     self._algo._bestSolution = self._algo._initializer()
 
-                self._algo._bestSolution._data = np.array(solutionData)
+                self._algo._bestsolution.setData(np.array(solutionData))
                 self._algo._bestSolution._score = float(data[2])
 
             macop_line(self._algo)

+ 4 - 4
macop/callbacks/multi.py

@@ -38,9 +38,9 @@ class MultiCheckpoint(Callback):
 
                 for solution in population:
                     solutionData = ""
-                    solutionSize = len(solution._data)
+                    solutionSize = len(solution.getData())
 
-                    for index, val in enumerate(solution._data):
+                    for index, val in enumerate(solution.getData()):
                         solutionData += str(val)
 
                         if index < solutionSize - 1:
@@ -139,9 +139,9 @@ class ParetoCheckpoint(Callback):
 
                 for solution in pfPop:
                     solutionData = ""
-                    solutionSize = len(solution._data)
+                    solutionSize = len(solution.getData())
 
-                    for index, val in enumerate(solution._data):
+                    for index, val in enumerate(solution.getData()):
                         solutionData += str(val)
 
                         if index < solutionSize - 1:

+ 11 - 1
macop/evaluators/base.py

@@ -10,7 +10,17 @@ from abc import abstractmethod
 class Evaluator():
     """Abstract Evaluator class which enables to compute solution using specific `_data` 
     """
-    def __init__(self, data):
+    def __init__(self, data: dict):
+                """Apply the computation of fitness from solution
+
+        Fitness is a float value for mono-objective or set of float values if multi-objective evaluation
+
+        Args:
+            solution: {Solution} -- Solution instance
+
+        Return:
+            {float} -- computed solution score (float or set of float if multi-objective evaluation)
+        """
         self._data = data
 
     @abstractmethod

+ 5 - 5
macop/evaluators/discrete/mono.py

@@ -38,7 +38,7 @@ class KnapsackEvaluator(Evaluator):
             {float} -- fitness score of solution
         """
         fitness = 0
-        for index, elem in enumerate(solution._data):
+        for index, elem in enumerate(solution.getData()):
             fitness += self._data['worths'][index] * elem
 
         return fitness
@@ -92,8 +92,8 @@ class QAPEvaluator(Evaluator):
             {float} -- fitness score of solution
         """
         fitness = 0
-        for index_i, val_i in enumerate(solution._data):
-            for index_j, val_j in enumerate(solution._data):
+        for index_i, val_i in enumerate(solution.getData()):
+            for index_j, val_j in enumerate(solution.getData()):
                 fitness += self._data['F'][index_i, index_j] * self._data['D'][val_i, val_j]
 
         return fitness
@@ -145,8 +145,8 @@ class UBQPEvaluator(Evaluator):
             {float} -- fitness score of solution
         """
         fitness = 0
-        for index_i, val_i in enumerate(solution._data):
-            for index_j, val_j in enumerate(solution._data):
+        for index_i, val_i in enumerate(solution.getData()):
+            for index_j, val_j in enumerate(solution.getData()):
                 fitness += self._data['Q'][index_i, index_j] * val_i * val_j
 
         return fitness

+ 10 - 10
macop/operators/discrete/crossovers.py

@@ -32,7 +32,7 @@ class SimpleCrossover(Crossover):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(20, 30) for i in range(10) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=10: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation
@@ -44,12 +44,12 @@ class SimpleCrossover(Crossover):
     >>> algo = IteratedLocalSearch(initializer, evaluator, operators, policy, validator, localSearch=local_search, maximise=True, verbose=False)
     >>> # using best solution, simple crossover is applied
     >>> best_solution = algo.run(100)
-    >>> list(best_solution._data)
+    >>> list(best_solution.getData())
     [1, 1, 0, 1, 0, 1, 1, 1, 0, 1]
     >>> new_solution_1 = initializer()
     >>> new_solution_2 = initializer()
     >>> offspring_solution = simple_crossover.apply(new_solution_1, new_solution_2)
-    >>> list(offspring_solution._data)
+    >>> list(offspring_solution.getData())
     [0, 1, 1, 0, 1, 0, 1, 1, 0, 1]
     """
     def apply(self, solution1, solution2=None):
@@ -74,9 +74,9 @@ class SimpleCrossover(Crossover):
         splitIndex = int(size / 2)
 
         if random.uniform(0, 1) > 0.5:
-            copy_solution._data[splitIndex:] = firstData[splitIndex:]
+            copy_solution.getData()[splitIndex:] = firstData[splitIndex:]
         else:
-            copy_solution._data[:splitIndex] = firstData[:splitIndex]
+            copy_solution.getData()[:splitIndex] = firstData[:splitIndex]
 
         return copy_solution
 
@@ -105,7 +105,7 @@ class RandomSplitCrossover(Crossover):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(20, 30) for i in range(10) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=10: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation
@@ -117,12 +117,12 @@ class RandomSplitCrossover(Crossover):
     >>> algo = IteratedLocalSearch(initializer, evaluator, operators, policy, validator, localSearch=local_search, maximise=True, verbose=False)
     >>> # using best solution, simple crossover is applied
     >>> best_solution = algo.run(100)
-    >>> list(best_solution._data)
+    >>> list(best_solution.getData())
     [1, 1, 1, 0, 1, 0, 1, 1, 1, 0]
     >>> new_solution_1 = initializer()
     >>> new_solution_2 = initializer()
     >>> offspring_solution = random_split_crossover.apply(new_solution_1, new_solution_2)
-    >>> list(offspring_solution._data)
+    >>> list(offspring_solution.getData())
     [0, 0, 0, 1, 1, 0, 0, 1, 0, 0]
     """
     def apply(self, solution1, solution2=None):
@@ -146,8 +146,8 @@ class RandomSplitCrossover(Crossover):
         splitIndex = random.randint(0, size)
 
         if random.uniform(0, 1) > 0.5:
-            copy_solution._data[splitIndex:] = firstData[splitIndex:]
+            copy_solution.getData()[splitIndex:] = firstData[splitIndex:]
         else:
-            copy_solution._data[:splitIndex] = firstData[:splitIndex]
+            copy_solution.getData()[:splitIndex] = firstData[:splitIndex]
 
         return copy_solution

+ 10 - 10
macop/operators/discrete/mutators.py

@@ -20,11 +20,11 @@ class SimpleMutation(Mutation):
     >>> from macop.solutions.discrete import BinarySolution
     >>> from macop.operators.discrete.mutators import SimpleMutation
     >>> solution = BinarySolution.random(5)
-    >>> list(solution._data)
+    >>> list(solution.getData())
     [1, 0, 0, 0, 1]
     >>> mutator = SimpleMutation()
     >>> mutation_solution = mutator.apply(solution)
-    >>> list(mutation_solution._data)
+    >>> list(mutation_solution.getData())
     [0, 0, 1, 0, 1]
     """
     def apply(self, solution):
@@ -49,11 +49,11 @@ class SimpleMutation(Mutation):
             firstCell = random.randint(0, size - 1)
             secondCell = random.randint(0, size - 1)
 
-        temp = copy_solution._data[firstCell]
+        temp = copy_solution.getData()[firstCell]
 
         # swicth values
-        copy_solution._data[firstCell] = copy_solution._data[secondCell]
-        copy_solution._data[secondCell] = temp
+        copy_solution.getData()[firstCell] = copy_solution.getData()[secondCell]
+        copy_solution.getData()[secondCell] = temp
 
         return copy_solution
 
@@ -70,11 +70,11 @@ class SimpleBinaryMutation(Mutation):
     >>> from macop.solutions.discrete import BinarySolution
     >>> from macop.operators.discrete.mutators import SimpleBinaryMutation
     >>> solution = BinarySolution.random(5)
-    >>> list(solution._data)
+    >>> list(solution.getData())
     [0, 1, 0, 0, 0]
     >>> mutator = SimpleBinaryMutation()
     >>> mutation_solution = mutator.apply(solution)
-    >>> list(mutation_solution._data)
+    >>> list(mutation_solution.getData())
     [1, 1, 0, 0, 0]
     """
     def apply(self, solution):
@@ -94,9 +94,9 @@ class SimpleBinaryMutation(Mutation):
         copy_solution = solution.clone()
 
         # swicth values
-        if copy_solution._data[cell]:
-            copy_solution._data[cell] = 0
+        if copy_solution.getData()[cell]:
+            copy_solution.getData()[cell] = 0
         else:
-            copy_solution._data[cell] = 1
+            copy_solution.getData()[cell] = 1
 
         return copy_solution

+ 1 - 1
macop/policies/reinforcement.py

@@ -46,7 +46,7 @@ class UCBPolicy(Policy):
     >>> evaluator = KnapsackEvaluator(data={'worths': worths})
     >>> # validator specification (based on weights of each objects)
     >>> weights = [ random.randint(5, 30) for i in range(20) ]
-    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution._data) if value == 1]) < 200 else False
+    >>> validator = lambda solution: True if sum([weights[i] for i, value in enumerate(solution.getData()) if value == 1]) < 200 else False
     >>> # initializer function with lambda function
     >>> initializer = lambda x=20: BinarySolution.random(x, validator)
     >>> # operators list with crossover and mutation

+ 18 - 3
macop/solutions/base.py

@@ -8,7 +8,7 @@ from copy import deepcopy
 class Solution():
     """Base abstract solution class structure
     
-    - stores solution data representation into `data` attribute
+    - stores solution data representation into ndarray `data` attribute
     - get size (shape) of specific data representation
     - stores the score of the solution
     """
@@ -17,8 +17,8 @@ class Solution():
         Abstract solution class constructor
 
         Attributes:
-            data: {ndarray} --  array of binary values
-            size: {int} -- size of binary array values
+            data: {ndarray} --  ndarray of values
+            size: {int} -- size of ndarray values
             score: {float} -- fitness score value
         """
         self._data = data
@@ -59,6 +59,21 @@ class Solution():
         """
         return self._score
 
+    def getData(self):
+        """
+        Returns solution data
+
+        Returns:
+            {ndarray} -- data values
+        """
+        return self._data
+
+    def setData(self, data):
+        """
+        Set solution data
+        """
+        self._data = data
+
     @staticmethod
     def random(size, validator=None):
         """

+ 12 - 12
macop/solutions/discrete.py

@@ -34,11 +34,11 @@ class BinarySolution(Solution):
         >>> data = [0, 1, 0, 1, 1]
         >>> solution = BinarySolution(data, len(data))
         >>> # check data content
-        >>> sum(solution._data) == 3
+        >>> sum(solution.getData()) == 3
         True
         >>> # clone solution
         >>> solution_copy = solution.clone()
-        >>> all(solution_copy._data == solution._data)
+        >>> all(solution_copy._data == solution.getData())
         True
         """
         super().__init__(np.array(data), size)
@@ -58,9 +58,9 @@ class BinarySolution(Solution):
         Example:
 
         >>> from macop.solutions.discrete import BinarySolution
-        >>> validator = lambda solution: True if sum(solution._data) > 5 else False
+        >>> validator = lambda solution: True if sum(solution.getData()) > 5 else False
         >>> solution = BinarySolution.random(10, validator)
-        >>> sum(solution._data) > 5
+        >>> sum(solution.getData()) > 5
         True
         """
 
@@ -105,10 +105,10 @@ class CombinatoryIntegerSolution(Solution):
         >>> import numpy as np
         >>> data = np.arange(5)
         >>> solution = CombinatoryIntegerSolution(data, 5)
-        >>> sum(solution._data) == 10
+        >>> sum(solution.getData()) == 10
         True
         >>> solution_copy = solution.clone()
-        >>> all(solution_copy._data == solution._data)
+        >>> all(solution_copy._data == solution.getData())
         True
         """
         super().__init__(data, size)
@@ -128,9 +128,9 @@ class CombinatoryIntegerSolution(Solution):
         Example:
 
         >>> from macop.solutions.discrete import CombinatoryIntegerSolution
-        >>> validator = lambda solution: True if sum(solution._data) > 5 else False
+        >>> validator = lambda solution: True if sum(solution.getData()) > 5 else False
         >>> solution = CombinatoryIntegerSolution.random(5, validator)
-        >>> sum(solution._data) > 5
+        >>> sum(solution.getData()) > 5
         True
         """
 
@@ -176,10 +176,10 @@ class IntegerSolution(Solution):
         >>> np.random.seed(42)
         >>> data = np.random.randint(5, size=10)
         >>> solution = IntegerSolution(data, 10)
-        >>> sum(solution._data)
+        >>> sum(solution.getData())
         28
         >>> solution_copy = solution.clone()
-        >>> all(solution_copy._data == solution._data)
+        >>> all(solution_copy._data == solution.getData())
         True
         """
         super().__init__(data, size)
@@ -201,9 +201,9 @@ class IntegerSolution(Solution):
         >>> from macop.solutions.discrete import IntegerSolution
         >>> import numpy as np
         >>> np.random.seed(42)
-        >>> validator = lambda solution: True if sum(solution._data) > 5 else False
+        >>> validator = lambda solution: True if sum(solution.getData()) > 5 else False
         >>> solution = IntegerSolution.random(5, validator)
-        >>> sum(solution._data) > 10
+        >>> sum(solution.getData()) > 10
         True
         """