Source code for metaheuristic_designer.initializers.composite_initializer

from typing import Iterable, Optional
from copy import copy

import numpy as np
from ..initializer import Initializer
from ..encoding import Encoding
from ..population import Population
from ..utils import IntVector, RealVector, RNGLike, VectorLike


[docs] class CompositeInitializer(Initializer): def __init__( self, dimension: int, initializers: Iterable[Initializer], weights: Optional[RealVector] = None, population_size: Optional[int] = None, encoding: Encoding = None, rng: Optional[RNGLike] = None, ): if population_size is None: population_size = initializers[0].population_size super().__init__(dimension, population_size, encoding=encoding, rng=rng) initializers = copy(initializers) for inits in initializers: inits.population_size = population_size self.initializers = initializers if weights is None: weights = np.ones(len(initializers)) else: weights = np.asarray(weights) weights = weights / np.sum(weights) self.weights = weights
[docs] def generate_random(self) -> VectorLike: """Generate a random individual from one initializers chosen at random. Returns ------- VectorLike A 1-D array generated by the fallback initializer. """ idx = self.rng.choice(len(self.initializers), p=self.weights) return self.initializers[idx].generate_random()
[docs] def generate_individual(self) -> VectorLike: """Generate an individual from one of the initializers chosen at random. Returns ------- ndarray A 1-D array representing the individual. """ idx = self.rng.choice(len(self.initializers), p=self.weights) return self.initializers[idx].generate_individual()
[docs] def generate_population(self, n_individuals=None): """Generate a population from individuals chosen at random from the initializers. Parameters ---------- objfunc: ObjectiveFunc Objective function that will be propagated to each individual. n_individual: int, optional Number of individuals to generate Returns ------- generated_population: Population Newly generated population. """ if n_individuals is None: n_individuals = self.population_size n_initializers = len(self.initializers) # Generate all populations from which to choose populations = [i.generate_population(n_individuals=n_individuals) for i in self.initializers] # Randomly choose individuals from each population population_tensor = np.asarray([p.genotype_matrix for p in populations]) choice_idx = self.rng.choice(n_initializers, n_individuals, p=self.weights) chosen_population = population_tensor[choice_idx, np.arange(n_individuals), :] return Population(genotype_matrix=chosen_population, encoding=self.encoding)
[docs] class FixedCompositeInitializer(Initializer): def __init__( self, dimension: int, initializers: Iterable[Initializer], amounts: Optional[IntVector] = None, population_size: Optional[int] = None, encoding: Encoding = None, rng: Optional[RNGLike] = None, ): if population_size is None: population_size = np.sum(amounts) super().__init__(dimension, population_size, encoding=encoding, rng=rng) initializers = copy(initializers) for inits in initializers: inits.population_size = population_size self.initializers = initializers self.init_counter = 0 if amounts is None: amounts = np.ones(len(initializers)) self.amounts = amounts self._amounts_cumsum = np.cumsum(amounts)
[docs] def generate_random(self) -> VectorLike: """Generate a random individual from one of the initializers chosen deterministically. Returns ------- VectorLike A 1-D array generated by the fallback initializer. """ idx = np.searchsorted(self._amounts_cumsum, self.init_counter, side="right") self.init_counter = (self.init_counter + 1) % np.sum(self.amounts) return self.initializers[idx].generate_random()
[docs] def generate_individual(self) -> VectorLike: """Generate an individual from one of the initializers chosen deterministically. Returns ------- ndarray A 1-D array representing the individual. """ idx = np.searchsorted(self._amounts_cumsum, self.init_counter, side="right") self.init_counter = (self.init_counter + 1) % np.sum(self.amounts) return self.initializers[idx].generate_individual()
[docs] def generate_population(self, n_individuals=None): """Generate a population from individuals chosen at random from the initializers. Parameters ---------- objfunc: ObjectiveFunc Objective function that will be propagated to each individual. n_individual: int, optional Number of individuals to generate Returns ------- generated_population: Population Newly generated population. """ if n_individuals is None: n_individuals = self.population_size n_initializers = len(self.initializers) # Generate all populations from which to choose populations = [i.generate_population(n_individuals=n_individuals) for i in self.initializers] # Choose individuals as indicated by the amount attribute population_tensor = np.asarray([p.genotype_matrix for p in populations]) cyclic_amounts = np.repeat(np.arange(n_initializers), self.amounts) choice_idx = np.resize(cyclic_amounts, n_individuals) chosen_population = population_tensor[choice_idx, np.arange(n_individuals), :] return Population(genotype_matrix=chosen_population, encoding=self.encoding)