Source code for moead_framework.tool.mop

import random
import numpy as np

from moead_framework.solution import OneDimensionSolution
from moead_framework.solution.base import Solution


def is_pareto_efficient(costs, return_mask = True):
    """
    Find the pareto-efficient points

    :param costs: An (n_points, n_costs) array
    :param return_mask: True to return a mask
    :return: An array of indices of pareto-efficient points.
        If return_mask is True, this will be an (n_points, ) boolean array
        Otherwise it will be a (n_efficient_points, ) integer array of indices.
    """
    is_efficient = np.arange(costs.shape[0])
    n_points = costs.shape[0]
    next_point_index = 0  # Next index in the is_efficient array to search for
    while next_point_index < len(costs):
        nondominated_point_mask = np.any(costs < costs[next_point_index], axis=1)
        nondominated_point_mask[next_point_index] = True
        is_efficient = is_efficient[nondominated_point_mask]  # Remove dominated points
        costs = costs[nondominated_point_mask]
        next_point_index = np.sum(nondominated_point_mask[:next_point_index])+1
    if return_mask:
        is_efficient_mask = np.zeros(n_points, dtype=bool)
        is_efficient_mask[is_efficient] = True
        return is_efficient_mask
    else:
        return is_efficient


[docs]def get_non_dominated(population): """ Return all non dominated solutions of the population :param population: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> :return: population: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> """ if type(population) != list: raise TypeError( f"the parameter 'population' of get_non_dominated(population) must be a list. Instead, we have {type(population)} ") arr = [] for s in population: if isinstance(s, Solution): arr.append(s.F) else: raise TypeError( f"the parameter 'population' of get_non_dominated(population) must be a list of Solution. Instead, we have a list of {type(s)} ") new_pop = list(population[i] for i in is_pareto_efficient(np.array(arr), return_mask=False)) return new_pop
[docs]def is_duplicated(x, population, number_of_objective): """ Identify if the solution x is already in the population :param number_of_objective: integer :param x: {:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`} :param population: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> :return: boolean """ for sol in population: is_dup = True for i in range(number_of_objective): if sol.F[i] != x.F[i]: is_dup = False break if is_dup: return True return False
[docs]def population_size_without_duplicate(population): """ Compute the population size without duplicate :param population: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> :return: integer: the size of the population """ if type(population) != list: raise TypeError( f"the parameter 'population' of population_size_without_duplicate(population) must be a list. Instead, we have {type(population)} ") arr = [] for s in population: if isinstance(s, Solution) | isinstance(s, OneDimensionSolution): arr.append(s.F) else: raise TypeError( f"the parameter 'population' of population_size_without_duplicate(population) must be a list of Solution. Instead, we have a list of {type(s)} ") arr = [] for ind in population: is_dup = False for ind_not_dup in arr: if np.array_equal(np.array(ind.decision_vector), np.array(ind_not_dup.decision_vector)): is_dup = True if not is_dup: arr.append(ind) return len(arr)
[docs]def compute_crowding_distance(s): """ Update the attribute distance of each solution with the crowding distance :param s: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> :return: population: list<{:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`}> with computed distances """ if not isinstance(s, list): raise TypeError( f"the parameter 's' of compute_crowding_distance(s) must be a list of Solution. Instead, we have {type(s)}") for individual in s: if isinstance(individual, Solution): individual.distance = 0 else: raise TypeError( f"the parameter 's' of compute_crowding_distance(s) must be a list of Solution. Instead, we have a list of {type(individual)} ") max_distance = 0 for m in range(len(s[0].F)): s.sort(key=lambda x: x[m]) for i in range(1, len(s) - 1): s[i].distance = s[i].distance + (s[i + 1][m] - s[i - 1][m]) max_distance = max(max_distance, s[i].distance) s[0].distance = max_distance s[len(s) - 1].distance = max_distance return s
def generate_weight_vectors(weight_file, shuffle=True): file = open(weight_file, 'r') file_content = list(map(str.strip, file.readlines())) weights = [] for row in file_content: weights.append(np.array(row.split(" ")).astype(np.float)) if shuffle: random.shuffle(weights) file.close() return weights