diff --git a/jmetal/lab/experiment.py b/jmetal/lab/experiment.py index b9d9b42a..8a97699d 100644 --- a/jmetal/lab/experiment.py +++ b/jmetal/lab/experiment.py @@ -50,6 +50,9 @@ def execute(self, output_path: str = ""): file_name = os.path.join(output_path, "TIME.{}".format(self.run_tag)) with open(file_name, "w+") as of: of.write(str(self.algorithm.total_computing_time)) + + def get_algorithm_data(self): + return self.algorithm.observable_data() class Experiment: @@ -63,12 +66,15 @@ def __init__(self, output_dir: str, jobs: List[Job], m_workers: int = 6): self.jobs = jobs self.m_workers = m_workers self.output_dir = output_dir + self.job_data = [] def run(self) -> None: with ProcessPoolExecutor(max_workers=self.m_workers) as executor: + for job in self.jobs: output_path = os.path.join(self.output_dir, job.algorithm_tag, job.problem_tag) executor.submit(job.execute(output_path)) + self.job_data.append(job.get_algorithm_data()) def generate_summary_from_experiment( diff --git a/jmetal/problem/__init__.py b/jmetal/problem/__init__.py index d0b2bfa3..502e7974 100644 --- a/jmetal/problem/__init__.py +++ b/jmetal/problem/__init__.py @@ -1,8 +1,8 @@ from .multiobjective.constrained import Srinivas, Tanaka -from .multiobjective.dtlz import DTLZ1, DTLZ2 +from .multiobjective.dtlz import * from .multiobjective.lz09 import LZ09_F2 from .multiobjective.unconstrained import Fonseca, Kursawe, Schaffer, Viennet2 -from .multiobjective.zdt import ZDT1, ZDT2, ZDT3, ZDT4, ZDT6 +from .multiobjective.zdt import ZDT1, ZDT2, ZDT3, ZDT4, ZDT5, ZDT6 from .singleobjective.tsp import TSP from .singleobjective.unconstrained import OneMax, Sphere @@ -15,10 +15,16 @@ "Viennet2", "DTLZ1", "DTLZ2", + "DTLZ3", + "DTLZ4", + "DTLZ5", + "DTLZ6", + "DTLZ7", "ZDT1", "ZDT2", "ZDT3", "ZDT4", + "ZDT5", "ZDT6", "LZ09_F2", "OneMax", diff --git a/jmetal/problem/multiobjective/dtlz.py b/jmetal/problem/multiobjective/dtlz.py index ab9935c7..32e3b61a 100644 --- a/jmetal/problem/multiobjective/dtlz.py +++ b/jmetal/problem/multiobjective/dtlz.py @@ -30,6 +30,9 @@ def __init__(self, number_of_variables: int = 7, number_of_objectives=3): def number_of_objectives(self) -> int: return len(self.obj_directions) + + def number_of_variables(self) -> int: + return len(self.lower_bound) def number_of_constraints(self) -> int: return 0 @@ -102,24 +105,24 @@ def __init__(self, number_of_variables: int = 12, number_of_objectives=3): super(DTLZ3, self).__init__(number_of_variables, number_of_objectives) def evaluate(self, solution: FloatSolution) -> FloatSolution: - k = self.number_of_variables - self.number_of_objectives + 1 + k = self.number_of_variables() - self.number_of_objectives() + 1 g = sum( - [(x - 0.5) ** 2 - cos(20.0 * pi * (x - 0.5)) for x in solution.variables[self.number_of_variables - k :]] + [(x - 0.5) ** 2 - cos(20.0 * pi * (x - 0.5)) for x in solution.variables[self.number_of_variables() - k :]] ) g = 100.0 * (k + g) - f = [1.0 + g for _ in range(self.number_of_objectives)] + f = [1.0 + g for _ in range(self.number_of_objectives())] - for i in range(self.number_of_objectives): - for j in range(self.number_of_objectives - (i + 1)): + for i in range(self.number_of_objectives()): + for j in range(self.number_of_objectives() - (i + 1)): f[i] *= cos(solution.variables[j] * 0.5 * pi) if i != 0: - aux = self.number_of_objectives - (i + 1) + aux = self.number_of_objectives() - (i + 1) f[i] *= sin(solution.variables[aux] * 0.5 * pi) - solution.objectives = [f[x] for x in range(self.number_of_objectives)] + solution.objectives = [f[x] for x in range(self.number_of_objectives())] return solution @@ -139,20 +142,20 @@ def __init__(self, number_of_variables: int = 12, number_of_objectives=3): def evaluate(self, solution: FloatSolution) -> FloatSolution: alpha = 100.0 - k = self.number_of_variables - self.number_of_objectives + 1 + k = self.number_of_variables() - self.number_of_objectives() + 1 - g = sum([(x - 0.5) ** 2 for x in solution.variables[self.number_of_variables - k :]]) - f = [1.0 + g for _ in range(self.number_of_objectives)] + g = sum([(x - 0.5) ** 2 for x in solution.variables[self.number_of_variables() - k :]]) + f = [1.0 + g for _ in range(self.number_of_objectives())] - for i in range(self.number_of_objectives): - for j in range(self.number_of_objectives - (i + 1)): + for i in range(self.number_of_objectives()): + for j in range(self.number_of_objectives() - (i + 1)): f[i] *= cos(pow(solution.variables[j], alpha) * pi / 2.0) if i != 0: - aux = self.number_of_objectives - (i + 1) + aux = self.number_of_objectives() - (i + 1) f[i] *= sin(pow(solution.variables[aux], alpha) * pi / 2.0) - solution.objectives = [f[x] for x in range(self.number_of_objectives)] + solution.objectives = [f[x] for x in range(self.number_of_objectives())] return solution @@ -171,26 +174,26 @@ def __init__(self, number_of_variables: int = 12, number_of_objectives=3): super(DTLZ5, self).__init__(number_of_variables, number_of_objectives) def evaluate(self, solution: FloatSolution) -> FloatSolution: - k = self.number_of_variables - self.number_of_objectives + 1 + k = self.number_of_variables() - self.number_of_objectives() + 1 - g = sum([(x - 0.5) ** 2 for x in solution.variables[self.number_of_variables - k :]]) + g = sum([(x - 0.5) ** 2 for x in solution.variables[self.number_of_variables() - k :]]) t = pi / (4.0 * (1.0 + g)) - theta = [0.0] * (self.number_of_objectives - 1) + theta = [0.0] * (self.number_of_objectives() - 1) theta[0] = solution.variables[0] * pi / 2.0 - theta[1:] = [t * (1.0 + 2.0 * g * solution.variables[i]) for i in range(1, self.number_of_objectives - 1)] + theta[1:] = [t * (1.0 + 2.0 * g * solution.variables[i]) for i in range(1, self.number_of_objectives() - 1)] - f = [1.0 + g for _ in range(self.number_of_objectives)] + f = [1.0 + g for _ in range(self.number_of_objectives())] - for i in range(self.number_of_objectives): - for j in range(self.number_of_objectives - (i + 1)): + for i in range(self.number_of_objectives()): + for j in range(self.number_of_objectives() - (i + 1)): f[i] *= cos(theta[j]) if i != 0: - aux = self.number_of_objectives - (i + 1) + aux = self.number_of_objectives() - (i + 1) f[i] *= sin(theta[aux]) - solution.objectives = [f[x] for x in range(self.number_of_objectives)] + solution.objectives = [f[x] for x in range(self.number_of_objectives())] return solution @@ -209,26 +212,26 @@ def __init__(self, number_of_variables: int = 12, number_of_objectives=3): super(DTLZ6, self).__init__(number_of_variables, number_of_objectives) def evaluate(self, solution: FloatSolution) -> FloatSolution: - k = self.number_of_variables - self.number_of_objectives + 1 + k = self.number_of_variables() - self.number_of_objectives() + 1 - g = sum([pow(x, 0.1) for x in solution.variables[self.number_of_variables - k :]]) + g = sum([pow(x, 0.1) for x in solution.variables[self.number_of_variables() - k :]]) t = pi / (4.0 * (1.0 + g)) - theta = [0.0] * (self.number_of_objectives - 1) + theta = [0.0] * (self.number_of_objectives() - 1) theta[0] = solution.variables[0] * pi / 2.0 - theta[1:] = [t * (1.0 + 2.0 * g * solution.variables[i]) for i in range(1, self.number_of_objectives - 1)] + theta[1:] = [t * (1.0 + 2.0 * g * solution.variables[i]) for i in range(1, self.number_of_objectives() - 1)] - f = [1.0 + g for _ in range(self.number_of_objectives)] + f = [1.0 + g for _ in range(self.number_of_objectives())] - for i in range(self.number_of_objectives): - for j in range(self.number_of_objectives - (i + 1)): + for i in range(self.number_of_objectives()): + for j in range(self.number_of_objectives() - (i + 1)): f[i] *= cos(theta[j]) if i != 0: - aux = self.number_of_objectives - (i + 1) + aux = self.number_of_objectives() - (i + 1) f[i] *= sin(theta[aux]) - solution.objectives = [f[x] for x in range(self.number_of_objectives)] + solution.objectives = [f[x] for x in range(self.number_of_objectives())] return solution @@ -247,17 +250,17 @@ def __init__(self, number_of_variables: int = 22, number_of_objectives=3): super(DTLZ7, self).__init__(number_of_variables, number_of_objectives) def evaluate(self, solution: FloatSolution) -> FloatSolution: - k = self.number_of_variables - self.number_of_objectives + 1 + k = self.number_of_variables() - self.number_of_objectives() + 1 - g = sum([x for x in solution.variables[self.number_of_variables - k :]]) + g = sum([x for x in solution.variables[self.number_of_variables() - k :]]) g = 1.0 + (9.0 * g) / k h = sum( - [(x / (1.0 + g)) * (1 + sin(3.0 * pi * x)) for x in solution.variables[: self.number_of_objectives - 1]] + [(x / (1.0 + g)) * (1 + sin(3.0 * pi * x)) for x in solution.variables[: self.number_of_objectives() - 1]] ) - h = self.number_of_objectives - h + h = self.number_of_objectives() - h - solution.objectives[: self.number_of_objectives - 1] = solution.variables[: self.number_of_objectives - 1] + solution.objectives[: self.number_of_objectives() - 1] = solution.variables[: self.number_of_objectives() - 1] solution.objectives[-1] = (1.0 + g) * h return solution diff --git a/jmetal/problem/multiobjective/zdt.py b/jmetal/problem/multiobjective/zdt.py index 1b8a7ed7..ab77ee65 100644 --- a/jmetal/problem/multiobjective/zdt.py +++ b/jmetal/problem/multiobjective/zdt.py @@ -31,6 +31,9 @@ def __init__(self, number_of_variables: int = 30): def number_of_objectives(self) -> int: return len(self.obj_directions) + + def number_of_variables(self) -> int: + return len(self.lower_bound) def number_of_constraints(self) -> int: return 0 @@ -135,6 +138,39 @@ def name(self): return "ZDT4" +class ZDT5(ZDT1): + """Problem ZDT5. + + .. note:: Bi-objective unconstrained problem. The default number of variables is 30. + .. note:: Continuous problem having a non-convex Pareto front + """ + + def evaluate(self, solution: FloatSolution) -> FloatSolution: + g = self.eval_g(solution) + h = self.eval_h(solution.variables[0], g) + + solution.objectives[0] = 1.0 + g + solution.objectives[1] = h * (1.0 - (solution.objectives[0] / h) ** 0.25) + + return solution + + def eval_g(self, solution: FloatSolution): + g = sum(solution.variables[1:]) / (solution.number_of_variables - 1) + + g = 1.0 + 9.0 * g + + return g + + def eval_h(self, f: float, g: float) -> float: + h = 1.0 - (f / g) ** 0.5 - (f / g) * sin(10.0 * pi * f) + + return h + + def name(self): + return "ZDT5" + + + class ZDT6(ZDT1): """Problem ZDT6.