evox.operators.crossover.differential_evolution 源代码

from typing import Tuple

import torch

from evox.utils import minimum_int


[文档] def DE_differential_sum( diff_padding_num: int, num_diff_vectors: torch.Tensor, index: torch.Tensor, population: torch.Tensor ) -> Tuple[torch.Tensor, torch.Tensor]: """ Computes the difference vectors' sum in differential evolution. :param diff_padding_num: The number of padding difference vectors. :param num_diff_vectors: The number of difference vectors used in mutation. :param index: The index of current individual. :param population: The population tensor. :return: The difference sum and the index of first difference vector. """ device = population.device pop_size = population.size(0) if num_diff_vectors.ndim == 0: num_diff_vectors = num_diff_vectors.unsqueeze(0) select_len = num_diff_vectors.unsqueeze(1) * 2 + 1 rand_indices = torch.randint(0, pop_size, (pop_size, diff_padding_num), device=device) rand_indices = torch.where(rand_indices == index.unsqueeze(1), pop_size - 1, rand_indices) pop_permute = population[rand_indices] mask = torch.arange(diff_padding_num, device=device).unsqueeze(0) < select_len pop_permute_padding = torch.where(mask.unsqueeze(2), pop_permute, 0) diff_vectors = pop_permute_padding[:, 1:] difference_sum = diff_vectors[:, 0::2].sum(dim=1) - diff_vectors[:, 1::2].sum(dim=1) return difference_sum, rand_indices[:, 0]
[文档] def DE_binary_crossover(mutation_vector: torch.Tensor, current_vector: torch.Tensor, CR: torch.Tensor): """ Performs binary crossover in differential evolution. :param mutation_vector: The mutated vector for each individual in the population. :param current_vector: The current vector for each individual in the population. :param CR: The crossover probability for each individual. :return: The trial vector after crossover for each individual. """ device = mutation_vector.device pop_size, dim = mutation_vector.size() if CR.ndim == 1: CR = CR.unsqueeze(1) mask = torch.randn(pop_size, dim, device=device) < CR rind = torch.randint(0, dim, (pop_size,), device=device).unsqueeze(1) jind = torch.arange(dim, device=device).unsqueeze(0) == rind trial_vector = torch.where(torch.logical_or(mask, jind), mutation_vector, current_vector) return trial_vector
[文档] def DE_exponential_crossover(mutation_vector: torch.Tensor, current_vector: torch.Tensor, CR: torch.Tensor): """ Performs exponential crossover in differential evolution. :param mutation_vector: The mutated vector for each individual in the population. :param current_vector: The current vector for each individual in the population. :param CR: The crossover probability for each individual. :return: The trial vector after crossover for each individual. """ device = mutation_vector.device pop_size, dim = mutation_vector.size() nn = torch.randint(0, dim, (pop_size,), device=device) # Geometric distribution random ll float_tiny = 1.1754943508222875e-38 ll = torch.rand(pop_size, device=device).clamp(min=float_tiny) ll = (ll.log() / (-CR.log1p())).floor().to(dtype=nn.dtype) mask = torch.arange(dim, device=device).unsqueeze(0) < (minimum_int(ll, dim) - 1).unsqueeze(1) mask = torch.gather(torch.tile(mask, (1, 2)), 1, nn.unsqueeze(1) + torch.arange(dim, device=device)) trial_vector = torch.where(mask, mutation_vector, current_vector) return trial_vector
[文档] def DE_arithmetic_recombination(mutation_vector: torch.Tensor, current_vector: torch.Tensor, K: torch.Tensor): """ Performs arithmetic recombination in differential evolution. :param mutation_vector: The mutated vector for each individual in the population. :param current_vector: The current vector for each individual in the population. :param K: The coefficient for each individual. :return: The trial vector after recombination for each individual. """ if K.ndim == 1: K = K.unsqueeze(1) trial_vector = current_vector + K * (mutation_vector - current_vector) return trial_vector