Source code for jmetal.algorithm.multiobjective.ibea
from typing import List, TypeVar
import numpy as np
from jmetal.algorithm.singleobjective.genetic_algorithm import GeneticAlgorithm
from jmetal.config import store
from jmetal.core.operator import Crossover, Mutation
from jmetal.core.problem import Problem
from jmetal.core.quality_indicator import EpsilonIndicator
from jmetal.operator.selection import BinaryTournamentSelection
from jmetal.util.comparator import SolutionAttributeComparator
from jmetal.util.evaluator import Evaluator
from jmetal.util.generator import Generator
from jmetal.util.termination_criterion import TerminationCriterion
S = TypeVar("S")
R = TypeVar("R")
[docs]
class IBEA(GeneticAlgorithm[S, R]):
def __init__(
self,
problem: Problem,
population_size: int,
offspring_population_size: int,
mutation: Mutation,
crossover: Crossover,
kappa: float,
termination_criterion: TerminationCriterion = store.default_termination_criteria,
population_generator: Generator = store.default_generator,
population_evaluator: Evaluator = store.default_evaluator,
):
"""Epsilon IBEA implementation as described in
* Zitzler, Eckart, and Simon Künzli. "Indicator-based selection in multiobjective search."
In International Conference on Parallel Problem Solving from Nature, pp. 832-842. Springer,
Berlin, Heidelberg, 2004.
https://link.springer.com/chapter/10.1007/978-3-540-30217-9_84
IBEA is a genetic algorithm (GA), i.e. it belongs to the evolutionary algorithms (EAs)
family. The multi-objective search in IBEA is guided by a fitness associated to every solution,
which is in turn controlled by a binary quality indicator. This implementation uses the so-called
additive epsilon indicator, along with a binary tournament mating selector.
:param problem: The problem to solve.
:param population_size: Size of the population.
:param mutation: Mutation operator (see :py:mod:`jmetal.operator.mutation`).
:param crossover: Crossover operator (see :py:mod:`jmetal.operator.crossover`).
:param kappa: Weight in the fitness computation.
"""
selection = BinaryTournamentSelection(
comparator=SolutionAttributeComparator(key="fitness", lowest_is_best=False)
)
self.kappa = kappa
super(IBEA, self).__init__(
problem=problem,
population_size=population_size,
offspring_population_size=offspring_population_size,
mutation=mutation,
crossover=crossover,
selection=selection,
termination_criterion=termination_criterion,
population_evaluator=population_evaluator,
population_generator=population_generator,
)
[docs]
def compute_fitness_values(self, population: List[S], kappa: float) -> List[S]:
for i in range(len(population)):
population[i].attributes["fitness"] = 0
for j in range(len(population)):
if j != i:
population[i].attributes["fitness"] += -np.exp(
-EpsilonIndicator([population[i].objectives]).compute([population[j].objectives]) / self.kappa
)
return population
[docs]
def create_initial_solutions(self) -> List[S]:
population = [self.population_generator.new(self.problem) for _ in range(self.population_size)]
population = self.compute_fitness_values(population, self.kappa)
return population
[docs]
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]:
join_population = population + offspring_population
join_population_size = len(join_population)
join_population = self.compute_fitness_values(join_population, self.kappa)
while join_population_size > self.population_size:
current_fitnesses = [individual.attributes["fitness"] for individual in join_population]
index_worst = current_fitnesses.index(min(current_fitnesses))
for i in range(join_population_size):
join_population[i].attributes["fitness"] += np.exp(
-EpsilonIndicator([join_population[i].objectives]).compute(
[join_population[index_worst].objectives]
)
/ self.kappa
)
join_population.pop(index_worst)
join_population_size = join_population_size - 1
return join_population
[docs]
def result(self) -> R:
return self.solutions
[docs]
def get_name(self) -> str:
return "Epsilon-IBEA"