Edit on GitHub

geneticalgorithm2.population_initializer

 1from typing import Callable, Optional, Tuple, Literal
 2
 3import numpy as np
 4
 5from .utils.aliases import TypeAlias, array1D, array2D
 6
 7
 8PopulationModifier: TypeAlias = Callable[[array2D, array1D], Tuple[array2D, array1D]]
 9"""
10function (population matrix, population scores) -> (new matrix, new scores)
11which will perform the bests selection and local optimization and other population transformations
12"""
13
14LOCAL_OPTIMIZATION_STEP_CASE: TypeAlias = Literal['before_select', 'after_select', 'never']
15"""
16When the local optimization (candidates enhancing) must be performed:
17    * 'never' -- don't do local optimization
18    * 'before_select' -- before selection best N objects 
19        (example: do local optimization for 5N objects and select N best results)
20    * 'after_select' -- do local optimization on best selected N objects
21"""
22
23
24def get_population_initializer(
25    select_best_of: int = 4,
26    local_optimization_step: LOCAL_OPTIMIZATION_STEP_CASE = 'never',
27    local_optimizer: Optional[
28        Callable[
29            [array1D, float],
30            Tuple[array1D, float]
31        ]
32    ] = None
33) -> Tuple[int, PopulationModifier]:
34    """
35    Args:
36        select_best_of: determines population size to select 1/select_best_of best part of start population.
37            For example, for select_best_of = 4 and population_size = N there will be selected N best objects
38                from 5N generated objects (if start_generation=None dictionary).
39            If start_generation is not None dictionary, there will be selected best (start_generation) / N objects
40        local_optimization_step: when to perform local optimization
41        local_optimizer: the local optimization function (object array, its score) -> (modified array, its score)
42
43    Returns:
44        select_best_of, population modifier
45    """
46    
47    assert select_best_of > 0 and isinstance(select_best_of, int), (select_best_of, type(select_best_of))
48
49    assert local_optimization_step in LOCAL_OPTIMIZATION_STEP_CASE.__args__, (
50        local_optimization_step, LOCAL_OPTIMIZATION_STEP_CASE.__args__
51    )
52
53    if local_optimizer is None and local_optimization_step in LOCAL_OPTIMIZATION_STEP_CASE.__args__[:2]:
54        raise Exception(
55            f"for local_optimization_step from {LOCAL_OPTIMIZATION_STEP_CASE.__args__[:2]} "
56            f"local_optimizer function mustn't be None"
57        )
58
59    def select_best(population: array2D, scores: array1D) -> Tuple[array2D, array1D]:
60        args = np.argsort(scores)
61        args = args[:round(args.size/select_best_of)]
62        return population[args], scores[args]
63
64    def local_opt(population: array2D, scores: array1D):
65        _pop, _score = zip(
66            *[
67                local_optimizer(population[i], scores[i]) for i in range(scores.size)
68            ]
69        )
70        return np.array(_pop), np.array(_score)
71
72    #def Create_population(func, start_generation, expected_size, #variable_boundaries):
73    #    
74    #    if not (start_generation['variables'] is None):
75    #        pop = start_generation['variables']
76    #        scores = start_generation['scores']
77    #        if scores is None:
78    #            scores = np.array([func(pop[i, :]) for i in range(pop.shape[0])])
79    #        return pop, scores
80
81    def process_population(population: array2D, scores: array1D):
82        if local_optimization_step == 'before_select':
83            pop, s = local_opt(population, scores)
84            return select_best(pop, s)
85
86        if local_optimization_step == 'after_select':
87            pop, s = select_best(population, scores)
88            return local_opt(pop, s)
89
90        #if local_optimization_step == 'never':
91        return select_best(population, scores)
92
93    return select_best_of, process_population
PopulationModifier: typing_extensions.TypeAlias = typing.Callable[[numpy.ndarray, numpy.ndarray], typing.Tuple[numpy.ndarray, numpy.ndarray]]

function (population matrix, population scores) -> (new matrix, new scores) which will perform the bests selection and local optimization and other population transformations

LOCAL_OPTIMIZATION_STEP_CASE: typing_extensions.TypeAlias = typing.Literal['before_select', 'after_select', 'never']

When the local optimization (candidates enhancing) must be performed: * 'never' -- don't do local optimization * 'before_select' -- before selection best N objects (example: do local optimization for 5N objects and select N best results) * 'after_select' -- do local optimization on best selected N objects

def get_population_initializer( select_best_of: int = 4, local_optimization_step: Literal['before_select', 'after_select', 'never'] = 'never', local_optimizer: Union[Callable[[numpy.ndarray, float], Tuple[numpy.ndarray, float]], NoneType] = None) -> Tuple[int, Callable[[numpy.ndarray, numpy.ndarray], Tuple[numpy.ndarray, numpy.ndarray]]]:
26def get_population_initializer(
27    select_best_of: int = 4,
28    local_optimization_step: LOCAL_OPTIMIZATION_STEP_CASE = 'never',
29    local_optimizer: Optional[
30        Callable[
31            [array1D, float],
32            Tuple[array1D, float]
33        ]
34    ] = None
35) -> Tuple[int, PopulationModifier]:
36    """
37    Args:
38        select_best_of: determines population size to select 1/select_best_of best part of start population.
39            For example, for select_best_of = 4 and population_size = N there will be selected N best objects
40                from 5N generated objects (if start_generation=None dictionary).
41            If start_generation is not None dictionary, there will be selected best (start_generation) / N objects
42        local_optimization_step: when to perform local optimization
43        local_optimizer: the local optimization function (object array, its score) -> (modified array, its score)
44
45    Returns:
46        select_best_of, population modifier
47    """
48    
49    assert select_best_of > 0 and isinstance(select_best_of, int), (select_best_of, type(select_best_of))
50
51    assert local_optimization_step in LOCAL_OPTIMIZATION_STEP_CASE.__args__, (
52        local_optimization_step, LOCAL_OPTIMIZATION_STEP_CASE.__args__
53    )
54
55    if local_optimizer is None and local_optimization_step in LOCAL_OPTIMIZATION_STEP_CASE.__args__[:2]:
56        raise Exception(
57            f"for local_optimization_step from {LOCAL_OPTIMIZATION_STEP_CASE.__args__[:2]} "
58            f"local_optimizer function mustn't be None"
59        )
60
61    def select_best(population: array2D, scores: array1D) -> Tuple[array2D, array1D]:
62        args = np.argsort(scores)
63        args = args[:round(args.size/select_best_of)]
64        return population[args], scores[args]
65
66    def local_opt(population: array2D, scores: array1D):
67        _pop, _score = zip(
68            *[
69                local_optimizer(population[i], scores[i]) for i in range(scores.size)
70            ]
71        )
72        return np.array(_pop), np.array(_score)
73
74    #def Create_population(func, start_generation, expected_size, #variable_boundaries):
75    #    
76    #    if not (start_generation['variables'] is None):
77    #        pop = start_generation['variables']
78    #        scores = start_generation['scores']
79    #        if scores is None:
80    #            scores = np.array([func(pop[i, :]) for i in range(pop.shape[0])])
81    #        return pop, scores
82
83    def process_population(population: array2D, scores: array1D):
84        if local_optimization_step == 'before_select':
85            pop, s = local_opt(population, scores)
86            return select_best(pop, s)
87
88        if local_optimization_step == 'after_select':
89            pop, s = select_best(population, scores)
90            return local_opt(pop, s)
91
92        #if local_optimization_step == 'never':
93        return select_best(population, scores)
94
95    return select_best_of, process_population
Arguments:
  • select_best_of: determines population size to select 1/select_best_of best part of start population. For example, for select_best_of = 4 and population_size = N there will be selected N best objects from 5N generated objects (if start_generation=None dictionary). If start_generation is not None dictionary, there will be selected best (start_generation) / N objects
  • local_optimization_step: when to perform local optimization
  • local_optimizer: the local optimization function (object array, its score) -> (modified array, its score)
Returns:

select_best_of, population modifier