+# ------ Optimizer for cga, sync_ga, alpha_cga, ccga and mcccga methods ------ #
+
+
+# ------------------------------ selection --------------------------------- #
+from selection.roulette_wheel_selection import RouletteWheelSelection
+from selection.tournament_selection import TournamentSelection
+from selection.selection_operator import SelectionOperator
+# -------------------------------------------------------------------------- #
+
+# ------------------------------ recombination ----------------------------- #
+from recombination.one_point_crossover import OnePointCrossover
+from recombination.pmx_crossover import PMXCrossover
+from recombination.two_point_crossover import TwoPointCrossover
+from recombination.uniform_crossover import UniformCrossover
+from recombination.byte_uniform_crossover import ByteUniformCrossover
+from recombination.byte_one_point_crossover import ByteOnePointCrossover
+from recombination.byte_one_point_crossover import ByteOnePointCrossover
+from recombination.flat_crossover import FlatCrossover
+from recombination.arithmetic_crossover import ArithmeticCrossover
+from recombination.blxalpha_crossover import BlxalphaCrossover
+from recombination.linear_crossover import LinearCrossover
+from recombination.unfair_avarage_crossover import UnfairAvarageCrossover
+from recombination.recombination_operator import RecombinationOperator
+# -------------------------------------------------------------------------- #
+
+# -------------------------------- mutation -------------------------------- #
+from mutation.bit_flip_mutation import BitFlipMutation
+from mutation.byte_mutation import ByteMutation
+from mutation.byte_mutation_random import ByteMutationRandom
+from mutation.insertion_mutation import InsertionMutation
+from mutation.shuffle_mutation import ShuffleMutation
+from mutation.swap_mutation import SwapMutation
+from mutation.two_opt_mutation import TwoOptMutation
+from mutation.float_uniform_mutation import FloatUniformMutation
+from mutation.mutation_operator import MutationOperator
+# -------------------------------------------------------------------------- #
+
+
+import random
+import numpy as np
+import byte_operators
+from population import *
+from individual import *
+from mutation.bit_flip_mutation import *
+from selection.tournament_selection import *
+from recombination.one_point_crossover import *
+from problems.single_objective.discrete.binary.one_max import *
+
+from typing import Callable, List, Tuple
+from collections.abc import Callable
+
+
+
+
+
[docs]
+
def cga(
+
n_cols: int,
+
n_rows: int,
+
n_gen: int,
+
ch_size: int,
+
gen_type: str,
+
p_crossover: float,
+
p_mutation: float,
+
problem: AbstractProblem,
+
selection: SelectionOperator,
+
recombination: RecombinationOperator,
+
mutation: MutationOperator,
+
mins : list[float] = [],
+
maxs : list[float] = []
+
) -> List:
+
"""
+
Optimize the given problem using a genetic algorithm.
+
+
Parameters
+
----------
+
n_cols : int
+
Number of columns in the population grid.
+
n_rows : int
+
Number of rows in the population grid.
+
n_gen : int
+
Number of generations to evolve.
+
ch_size : int
+
Size of the chromosome.
+
gen_type : str
+
Type of the genome representation (e.g., 'Binary', 'Permutation', 'Real').
+
p_crossover : float
+
Probability of crossover (between 0 and 1).
+
p_mutation : float
+
Probability of mutation (between 0 and 1).
+
known_best : float
+
Known best solution for gap calculation.
+
k_tournament : int
+
Size of the tournament for selection.
+
problem : AbstractProblem
+
The problem instance used for fitness evaluation.
+
selection : SelectionOperator
+
Function or class used for selecting parents.
+
recombination : RecombinationOperator
+
Function or class used for recombination (crossover).
+
mutation : MutationOperator
+
Function or class used for mutation.
+
mins : list[float]
+
List of minimum values for each gene in the chromosome (for real value optimization).
+
maxs : list[float]
+
List of maximum values for each gene in the chromosome (for real value optimization).
+
+
Returns
+
-------
+
List
+
A list containing the best solution found during the optimization process,
+
where the first element is the chromosome, the second is the fitness value,
+
and the third is the generation at which it was found.
+
"""
+
+
pop_size = n_cols * n_rows
+
best_solutions = []
+
best_objectives = []
+
best_ever_solution = []
+
avg_objectives = []
+
method_name = OptimizationMethod.CGA
+
+
# Generate Initial Population
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, mins=mins, maxs=maxs).initial_population()
+
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
0,
+
]
+
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
# Evolutionary Algorithm Loop
+
generation = 1
+
while generation != n_gen + 1:
+
for c in range(pop_size):
+
offsprings = []
+
parents = selection(pop_list, c).get_parents()
+
rnd = np.random.rand()
+
+
if rnd < p_crossover:
+
offsprings = recombination(
+
parents, problem).get_recombinations()
+
else:
+
offsprings = parents
+
+
for p in range(len(offsprings)):
+
+
mutation_cand = offsprings[p]
+
+
# for byte_mutation_dynamic and byte_mutation_random_dynamic
+
# p_mutation = p_mutation - ((g/n_gen)*p_mutation)
+
+
rnd = np.random.rand()
+
+
if rnd < p_mutation:
+
mutated = mutation(mutation_cand, problem).mutate()
+
offsprings[p] = mutated
+
else:
+
pass
+
+
# Replacement: Replace if better
+
if offsprings[p].fitness_value < parents[p].fitness_value:
+
index = pop_list.index(parents[p])
+
new_p = offsprings[p]
+
old_p = pop_list[index]
+
pop_list[index] = new_p
+
+
else:
+
pass
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
+
if (pop_list_ordered[0].fitness_value) < best_ever_solution[1]:
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
generation,
+
]
+
else:
+
pass
+
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
generation += 1
+
+
return best_ever_solution
+
+
+
+
[docs]
+
def sync_cga(
+
n_cols: int,
+
n_rows: int,
+
n_gen: int,
+
ch_size: int,
+
gen_type: str,
+
p_crossover: float,
+
p_mutation: float,
+
problem: Callable[[List[float]], float],
+
selection: SelectionOperator,
+
recombination: RecombinationOperator,
+
mutation: MutationOperator,
+
mins: List[float] = [],
+
maxs: List[float] = []
+
) -> List:
+
"""
+
Optimize the given problem using a synchronous cellular genetic algorithm (Sync-CGA).
+
+
Parameters
+
----------
+
n_cols : int
+
Number of columns in the population grid.
+
n_rows : int
+
Number of rows in the population grid.
+
n_gen : int
+
Number of generations to evolve.
+
ch_size : int
+
Size of the chromosome.
+
gen_type : str
+
Type of the genome representation (e.g., 'Binary', 'Permutation', 'Real').
+
p_crossover : float
+
Probability of crossover between parents.
+
p_mutation : float
+
Probability of mutation in offspring.
+
problem : Callable[[List[float]], float]
+
Function to evaluate the fitness of a solution. Takes a list of floats and returns a float.
+
selection : SelectionOperator
+
Function or class used for selecting parents.
+
recombination : RecombinationOperator
+
Function or class used for recombination (crossover).
+
mutation : MutationOperator
+
Function or class used for mutation.
+
mins : List[float]
+
List of minimum values for each gene in the chromosome (for real value optimization).
+
maxs : List[float]
+
List of maximum values for each gene in the chromosome (for real value optimization
+
+
Returns
+
-------
+
List
+
A list containing the best solution found during the optimization process,
+
where the first element is the chromosome, the second is the fitness value,
+
and the third is the generation at which it was found.
+
"""
+
+
pop_size = n_cols * n_rows
+
best_solutions = []
+
best_objectives = []
+
best_ever_solution = []
+
avg_objectives = []
+
method_name = OptimizationMethod.SYNCGA
+
+
+
# Generate Initial Population
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, mins = mins, maxs=maxs).initial_population()
+
+
# Sort population by fitness value
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
# Track the best solution in the initial population
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
0,
+
]
+
+
# Calculate the mean fitness for the initial population
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
# Evolutionary Algorithm Loop
+
generation = 1
+
aux_poplist = []
+
+
while generation != n_gen + 1:
+
aux_poplist = pop_list.copy() # Create a copy of the population for synchronous update
+
+
for c in range(pop_size):
+
offsprings = []
+
# Select parents
+
parents = selection(pop_list, c).get_parents()
+
rnd = np.random.rand()
+
+
# Apply crossover with probability p_crossover
+
if rnd < p_crossover:
+
offsprings = recombination(parents, problem).get_recombinations()
+
else:
+
offsprings = parents
+
+
for p in range(len(offsprings)):
+
mutation_cand = offsprings[p]
+
rnd = np.random.rand()
+
+
# Apply mutation with probability p_mutation
+
if rnd < p_mutation:
+
mutated = mutation(mutation_cand, problem).mutate()
+
offsprings[p] = mutated
+
+
# Replacement: Replace if offspring is better
+
if offsprings[p].fitness_value < parents[p].fitness_value:
+
index = pop_list.index(parents[p])
+
aux_poplist[index] = offsprings[p]
+
+
# Update population synchronously
+
pop_list = aux_poplist
+
pop_list_ordered = sorted(pop_list, key=lambda x: x.fitness_value)
+
+
# Track best solutions
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
+
# Update best ever solution if the current solution is better
+
if pop_list_ordered[0].fitness_value < best_ever_solution[1]:
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
generation,
+
]
+
+
# Calculate the mean fitness for the current generation
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
generation += 1
+
+
return best_ever_solution
+
+
+
+
[docs]
+
def alpha_cga(
+
n_cols: int,
+
n_rows: int,
+
n_gen: int,
+
ch_size: int,
+
gen_type: str,
+
p_crossover: float,
+
p_mutation: float,
+
problem: AbstractProblem,
+
selection: SelectionOperator,
+
recombination: RecombinationOperator,
+
mutation: MutationOperator,
+
mins: List[float] = [],
+
maxs: List[float] = []
+
) -> List:
+
"""
+
Optimize a problem using an evolutionary algorithm with an alpha-male exchange mechanism.
+
+
Parameters
+
----------
+
n_cols : int
+
Number of columns in the grid for the population.
+
n_rows : int
+
Number of rows in the grid for the population.
+
n_gen : int
+
Number of generations to run the optimization.
+
ch_size : int
+
Size of the chromosome.
+
gen_type : GeneType
+
Type of genome representation (GeneType.BINARY, GeneType.PERMUTATION, or GeneType.REAL).
+
p_crossover : float
+
Probability of crossover, should be between 0 and 1.
+
p_mutation : float
+
Probability of mutation, should be between 0 and 1.
+
known_best : float
+
Known best solution value for gap calculation.
+
k_tournament : int
+
Tournament size for selection.
+
problem : AbstractProblem
+
The problem instance used to evaluate fitness.
+
selection : SelectionOperator
+
Function used for selection in the evolutionary algorithm.
+
recombination : RecombinationOperator
+
Function used for recombination (crossover) in the evolutionary algorithm.
+
mutation : MutationOperator
+
Function used for mutation in the evolutionary algorithm.
+
mins : List[float]
+
List of minimum values for each gene in the chromosome (for real value optimization).
+
maxs : List[float]
+
List of maximum values for each gene in the chromosome (for real value optimization).
+
+
Returns
+
-------
+
List
+
A list containing the best solution found during the optimization process,
+
where the first element is the chromosome, the second is the fitness value,
+
and the third is the generation at which it was found.
+
"""
+
+
pop_size = n_cols * n_rows
+
best_solutions = []
+
best_objectives = []
+
best_ever_solution = []
+
avg_objectives = []
+
method_name = OptimizationMethod.ALPHA_CGA
+
+
+
# Generate Initial Population
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, mins=mins, maxs=maxs).initial_population()
+
+
# Sort population by fitness value
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
# Initialize tracking of best solutions
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
0,
+
]
+
+
# Calculate mean fitness for the initial population
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
# Optimization loop
+
generation = 1
+
+
while generation != n_gen + 1:
+
for c in range(0, pop_size, n_cols):
+
# Alpha-male exchange mechanism
+
if generation % 10 == 0:
+
rnd1 = rd.randrange(1, pop_size + 1, n_cols)
+
rnd2 = rd.randrange(1, pop_size + 1, n_cols)
+
while rnd1 == rnd2:
+
rnd2 = np.random.randint(1, n_cols + 1)
+
+
alpha_male1 = pop_list[rnd1]
+
alpha_male2 = pop_list[rnd2]
+
+
pop_list[rnd2] = alpha_male1
+
pop_list[rnd1] = alpha_male2
+
+
for n in range(n_cols):
+
offsprings = []
+
parents = []
+
+
p1 = pop_list[c]
+
p2 = pop_list[c + n]
+
parents.append(p1)
+
parents.append(p2)
+
+
rnd = np.random.rand()
+
+
# Apply crossover with probability p_crossover
+
if rnd < p_crossover:
+
offsprings = recombination(
+
parents, problem).get_recombinations()
+
else:
+
offsprings = parents
+
+
for p in range(len(offsprings)):
+
+
mutation_cand = offsprings[p]
+
rnd = np.random.rand()
+
+
# Apply mutation with probability p_mutation
+
if rnd < p_mutation:
+
mutated = mutation(mutation_cand, problem).mutate()
+
offsprings[p] = mutated
+
+
# Replacement: Replace if offspring is better
+
if offsprings[p].fitness_value < parents[1].fitness_value:
+
try:
+
index = pop_list.index(parents[1])
+
except ValueError:
+
continue
+
new_p = offsprings[p]
+
pop_list[index] = new_p
+
+
# Sort population and update best solutions
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
+
# Update best ever solution if current solution is better
+
if pop_list_ordered[0].fitness_value < best_ever_solution[1]:
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
generation,
+
]
+
+
# Update average objectives
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
generation += 1
+
+
return best_ever_solution
+
+
+
+
[docs]
+
def ccga(
+
n_cols: int,
+
n_rows: int,
+
n_gen: int,
+
ch_size: int,
+
gen_type: str,
+
problem: AbstractProblem,
+
selection: SelectionOperator,
+
mins: List[float] = [],
+
maxs: List[float] = []
+
) -> List:
+
"""
+
Perform optimization using a (CCGA).
+
+
Parameters
+
----------
+
n_cols : int
+
Number of columns in the grid for the population.
+
n_rows : int
+
Number of rows in the grid for the population.
+
n_gen : int
+
Number of generations to run the optimization.
+
ch_size : int
+
Size of the chromosome.
+
gen_type : GeneType
+
Type of genome representation (GeneType.BINARY, Genetype.PERMUTATION, GeneType.REAL).
+
problem : AbstractProblem
+
The problem instance used to evaluate fitness.
+
selection : SelectionOperator
+
Function used for selection in the evolutionary algorithm.
+
mins : List[float]
+
List of minimum values for each gene in the chromosome (for real value optimization).
+
maxs : List[float]
+
List of maximum values for each gene in the chromosome (for real value optimization
+
+
+
Returns
+
-------
+
List
+
A list containing the best solution found during the optimization process,
+
where the first element is the chromosome, the second is the fitness value,
+
and the third is the generation at which it was found.
+
"""
+
+
pop_size = n_cols * n_rows
+
best_solutions = []
+
best_objectives = []
+
best_ever_solution = []
+
avg_objectives = []
+
vector = [0.5 for _ in range(ch_size)]
+
method_name = OptimizationMethod.CCGA
+
+
+
# Generate Initial Population
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, vector,mins=mins, maxs=maxs).initial_population()
+
+
# Sort population by fitness value
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
# Initialize tracking of best solutions
+
best_solutions.append(pop_list_ordered[0].chromosome)
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
best_ever_solution = [
+
pop_list_ordered[0].chromosome,
+
pop_list_ordered[0].fitness_value,
+
0,
+
]
+
+
# Calculate mean fitness for the initial population
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
best = pop_list_ordered[0]
+
+
# Evolutionary Algorithm Loop
+
generation = 1
+
while generation != n_gen + 1:
+
for c in range(pop_size):
+
# Select parents and determine the winner and loser
+
parents = selection(pop_list, c).get_parents()
+
p1 = parents[0]
+
p2 = parents[1]
+
+
winner, loser = compete(p1, p2)
+
+
if winner.fitness_value > best.fitness_value:
+
best = winner
+
+
# Update the vector based on the winner and loser
+
update_vector(vector, winner, loser, pop_size)
+
+
# Re-generate the population based on the updated vector
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, vector).initial_population()
+
+
# Update best ever solution if current solution is better
+
if best.fitness_value > best_ever_solution[1]:
+
best_ever_solution = [
+
best.chromosome,
+
best.fitness_value,
+
generation,
+
]
+
+
# Update average objectives
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
+
generation += 1
+
+
return best_ever_solution
+
+
+
+
+
[docs]
+
def mcccga(
+
n_cols: int,
+
n_rows: int,
+
n_gen: int,
+
ch_size: int,
+
gen_type: str,
+
problem: Callable[[List[float]], float],
+
selection: SelectionOperator,
+
mins: list[float],
+
maxs: list[float]
+
) -> List:
+
"""
+
Optimize the given problem using a multi-population machine-coded compact genetic algorithm (MCCGA).
+
+
Parameters
+
----------
+
n_cols : int
+
Number of columns in the population grid.
+
n_rows : int
+
Number of rows in the population grid.
+
n_gen : int
+
Number of generations to evolve.
+
ch_size : int
+
Size of the chromosome.
+
gen_type : str
+
Type of the genome representation (e.g., 'Binary', 'Permutation', 'Real').
+
problem : Callable[[List[float]], float]
+
Function to evaluate the fitness of a solution. Takes a list of floats and returns a float.
+
selection : Callable
+
Function or class used for selecting parents.
+
mins : List[float]
+
List of minimum values for the probability vector generation.
+
maxs : List[float]
+
List of maximum values for the probability vector generation.
+
+
Returns
+
-------
+
List
+
A list containing the best solution found during the optimization process,
+
where the first element is the chromosome, the second is the fitness value,
+
and the third is the generation at which it was found.
+
"""
+
+
pop_size = n_cols * n_rows
+
best_objectives = []
+
best_ever_solution = []
+
avg_objectives = []
+
method_name = OptimizationMethod.MCCCGA
+
+
# Generate initial probability vector
+
vector = generate_probability_vector(mins, maxs, pop_size)
+
+
# Generate Initial Population
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, vector).initial_population()
+
+
# Sort population by fitness value
+
pop_list_ordered = sorted(
+
pop_list, key=lambda x: x.fitness_value)
+
+
# Track the best solution in the initial population
+
best_objectives.append(pop_list_ordered[0].fitness_value)
+
best_byte_ch = byte_operators.bits_to_floats(
+
pop_list_ordered[0].chromosome)
+
best_ever_solution = [
+
best_byte_ch,
+
pop_list_ordered[0].fitness_value,
+
1,
+
]
+
+
# Calculate the mean fitness for the initial population
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
best = pop_list_ordered[0]
+
+
# Evolutionary Algorithm Loop
+
generation = 1
+
while generation != n_gen + 1:
+
for c in range(pop_size):
+
+
# Select parents from the population
+
parents = selection(pop_list, c).get_parents()
+
p1 = parents[0]
+
p2 = parents[1]
+
+
# Compete parents and identify the winner and loser
+
winner, loser = compete(p1, p2)
+
if winner.fitness_value < best.fitness_value:
+
best = winner
+
+
# Update the probability vector based on the competition result
+
update_vector(vector, winner, loser, pop_size)
+
+
# Re-generate the population based on the updated vector
+
pop_list = Population(method_name, ch_size, n_rows, n_cols,
+
gen_type, problem, vector).initial_population()
+
+
# Track the best fitness value and update the best solution if necessary
+
best_objectives.append(best.fitness_value)
+
best_byte_ch = byte_operators.bits_to_floats(
+
pop_list_ordered[0].chromosome)
+
+
if best.fitness_value < best_ever_solution[1]:
+
best_ever_solution = [
+
best_byte_ch,
+
best.fitness_value,
+
generation,
+
]
+
+
# Calculate the mean fitness for the current generation
+
mean = sum(map(lambda x: x.fitness_value, pop_list)) / len(pop_list)
+
avg_objectives.append(mean)
+
best_byte_ch = byte_operators.bits_to_floats(best.chromosome)
+
+
generation += 1
+
+
# Evaluate the final solution sampled from the probability vector
+
best_byte_ch = byte_operators.bits_to_floats(sample(vector))
+
best_byte_result = problem.f(best_byte_ch)
+
+
# Update the best-ever solution if the sampled solution is better
+
if best_byte_result <= best_ever_solution[1]:
+
best_ever_solution[0] = best_byte_ch
+
best_ever_solution[1] = best_byte_result
+
+
return best_ever_solution
+
+
+
+
+
[docs]
+
def compete(p1: Individual, p2: Individual) -> Tuple[Individual, Individual]:
+
"""
+
Compete between two individuals to determine the better one.
+
+
Parameters
+
----------
+
p1 : Individual
+
First individual.
+
p2 : Individual
+
Second individual.
+
+
Returns
+
-------
+
Tuple[Individual, Individual]
+
The better individual and the loser.
+
"""
+
if p1.fitness_value < p2.fitness_value:
+
return p1, p2
+
else:
+
return p2, p1
+
+
+
+
+
[docs]
+
def update_vector(vector: List[float], winner: Individual, loser: Individual, pop_size: int):
+
"""
+
Update the probability vector based on the winner and loser individuals.
+
+
Parameters
+
----------
+
vector : List[float]
+
Probability vector to be updated.
+
winner : Individual
+
The winning individual.
+
loser : Individual
+
The losing individual.
+
pop_size : int
+
Size of the population.
+
"""
+
for i in range(len(vector)):
+
if winner.chromosome[i] != loser.chromosome[i]:
+
if winner.chromosome[i] == 1:
+
vector[i] += round((1.0 / float(pop_size)), 3)
+
else:
+
vector[i] -= round((1.0 / float(pop_size)), 3)
+
+
+
+
+
[docs]
+
def random_vector_between(mins: List[float], maxs: List[float]) -> List[float]:
+
"""
+
Generate a random vector of floats between the given minimum and maximum values.
+
+
Parameters
+
----------
+
mins : List[float]
+
List of minimum values.
+
maxs : List[float]
+
List of maximum values.
+
+
Returns
+
-------
+
List[float]
+
Randomly generated vector.
+
"""
+
n = len(mins)
+
result = [0.0] * n
+
+
for i in range(n):
+
result[i] = mins[i] + random.random() * (maxs[i] - mins[i])
+
+
return result
+
+
+
+
+
[docs]
+
def generate_probability_vector(mins: List[float], maxs: List[float], ntries: int) -> List[float]:
+
"""
+
Generate a probability vector based on the given minimum and maximum values.
+
+
Parameters
+
----------
+
mins : List[float]
+
List of minimum values.
+
maxs : List[float]
+
List of maximum values.
+
ntries : int
+
Number of trials for generating the probability vector.
+
+
Returns
+
-------
+
List[float]
+
Probability vector.
+
"""
+
nbits = len(mins) * 32
+
mutrate = 1.0 / ntries
+
probvector = [0.0] * nbits
+
+
for _ in range(ntries):
+
floats = random_vector_between(mins, maxs)
+
floatbits = byte_operators.floats_to_bits(floats)
+
for k in range(nbits):
+
if floatbits[k] == 1:
+
probvector[k] = probvector[k] + mutrate
+
+
return probvector
+
+
+
+
[docs]
+
def sample(probvector: List[float]) -> List[int]:
+
"""
+
Sample a vector based on the provided probability vector.
+
+
Parameters
+
----------
+
probvector : List[float]
+
Probability vector for sampling.
+
+
Returns
+
-------
+
List[int]
+
Sampled binary vector.
+
"""
+
n = len(probvector)
+
newvector = [0] * n
+
+
for i in range(n):
+
if random.random() < probvector[i]:
+
newvector[i] = 1
+
+
return newvector
+
+
+
+
+