Skip to content

Commit

Permalink
updater refactor, naming
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoran Jankovic committed Jun 16, 2024
1 parent 09b140a commit 5e68d90
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 74 deletions.
18 changes: 18 additions & 0 deletions gadapt/adapters/ga_logging/logging_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,21 @@ def gadapt_log_info(msg: str):
logger.info(msg)
except Exception:
pass


def gadapt_log_warning(msg: str):
logger = logging.getLogger("gadapt_logger")
if logger.disabled:
return
try:
logger.warning(msg)
except Exception:
pass


def gadapt_log_error(msg: str):
logger = logging.getLogger("gadapt_logger")
try:
logger.error(msg)
except Exception:
pass
2 changes: 1 addition & 1 deletion gadapt/execution/ga_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def find_costs(self):
self.population.previous_avg_cost = self.population.avg_cost
self.population.previous_min_cost = self.population.min_cost
self.cost_finder.find_costs(self.population)
self.gene_updater.update_variables(self.population)
self.gene_updater.update_genes(self.population)
self.population_updater.update_population(self.population)

def immigrate(self):
Expand Down
62 changes: 45 additions & 17 deletions gadapt/factory/ga_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@
from operations.chromosome_update.parent_diversity_chromosome_updater import (
ParentDiversityChromosomeUpdater,
)
from operations.gene_update.base_gene_updater import BaseGeneUpdater
from operations.population_update.base_population_updater import BasePopulationUpdater


class GAFactory(BaseGAFactory):
Expand Down Expand Up @@ -509,21 +511,7 @@ def _get_crossover(self) -> BaseCrossover:
"""
if self._ga is None:
raise Exception("ga object must not be None!")
mutator_strings = [
ms.strip()
for ms in self._ga.population_mutation.split(definitions.PARAM_SEPARATOR)
]
population_mutation_selection_strings = [
value
for value in mutator_strings
if value in definitions.POPULATION_MUTATION_SELECTION_STRINGS
]
chromosome_updater: BaseChromosomeUpdater = BaseChromosomeUpdater()
if (
not population_mutation_selection_strings
or definitions.PARENT_DIVERSITY in mutator_strings
):
chromosome_updater = ParentDiversityChromosomeUpdater()
chromosome_updater = self.get_chromosome_updater()

if self._ga.crossover == definitions.BLENDING:
return BlendingCrossover(chromosome_updater)
Expand All @@ -535,10 +523,50 @@ def _get_gene_updater(self):
"""
Gene Updater Instance
"""
return CrossDiversityGeneUpdater()
population_mutator_strings = [
ms.strip()
for ms in self._ga.population_mutation.split(definitions.PARAM_SEPARATOR)
]
chromosome_mutator_strings = [
ms.strip()
for ms in self._ga.chromosome_mutation.split(definitions.PARAM_SEPARATOR)
]
gene_mutator_strings = [
ms.strip()
for ms in self._ga.gene_mutation.split(definitions.PARAM_SEPARATOR)
]
all_mutator_strings = (
population_mutator_strings
+ chromosome_mutator_strings
+ gene_mutator_strings
)
if definitions.CROSS_DIVERSITY in all_mutator_strings:
return CrossDiversityGeneUpdater()
return BaseGeneUpdater()

def get_chromosome_updater(self):
population_mutator_strings = [
ms.strip()
for ms in self._ga.population_mutation.split(definitions.PARAM_SEPARATOR)
]
if (
not population_mutator_strings
or definitions.PARENT_DIVERSITY in population_mutator_strings
):
return ParentDiversityChromosomeUpdater()
return BaseChromosomeUpdater()

def _get_population_updater(self):
"""
Population Updater Instance
"""
return CostDiversityPopulationUpdater()
population_mutator_strings = [
ms.strip()
for ms in self._ga.population_mutation.split(definitions.PARAM_SEPARATOR)
]
if (
not population_mutator_strings
or definitions.COST_DIVERSITY in population_mutator_strings
):
return CostDiversityPopulationUpdater()
return BasePopulationUpdater()
11 changes: 6 additions & 5 deletions gadapt/ga_model/chromosome.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(
population_generation: population generation
"""
super().__init__()
self._parent_diversity_coefficient = float("NaN")
self._cost_value = definitions.FLOAT_NAN
self._is_immigrant = False
self._population_generation = population_generation
Expand Down Expand Up @@ -171,15 +172,15 @@ def add_gene(self, gen_var: Gene, gen_var_value: float = definitions.FLOAT_NAN):
self.append(g)

@property
def parent_diversity(self) -> float:
def parent_diversity_coefficient(self) -> float:
"""
Diversity of parents
"""
return self._parent_diversity
return self._parent_diversity_coefficient

@parent_diversity.setter
def parent_diversity(self, value: float):
self._parent_diversity = value
@parent_diversity_coefficient.setter
def parent_diversity_coefficient(self, value: float):
self._parent_diversity_coefficient = value

@property
def population_generation(self) -> int:
Expand Down
4 changes: 2 additions & 2 deletions gadapt/ga_model/population.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def __init__(self, options: GAOptions):
self.chromosomes: List[Chromosome] = []
self.generate_initial_population()
self.start_time = datetime.now()
self.average_cost_step = float("NaN")
self.average_cost_step_in_first_population = float("NaN")
self.absolute_cost_diversity = float("NaN")
self.absolute_cost_diversity_in_first_population = float("NaN")
self.timeout_expired = False
self.min_cost_per_generation: List[float] = []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def chromosome_prepare_update(self, mother_gene: Allele, father_gene: Allele):

def chromosome_update(self, offspring1: Chromosome, offspring2: Chromosome):
parent_diversity = self._get_parent_diversity()
offspring1.parent_diversity = parent_diversity
offspring2.parent_diversity = parent_diversity
offspring1.parent_diversity_coefficient = parent_diversity
offspring2.parent_diversity_coefficient = parent_diversity

def chromosome_start_update(self, *args, **kwargs):
self._genetic_diversity = []
12 changes: 4 additions & 8 deletions gadapt/operations/gene_update/base_gene_updater.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
from abc import ABC, abstractmethod


class BaseGeneUpdater(ABC):
class BaseGeneUpdater:
"""
Base class for variable update
"""

def __init__(self):
self.population = None

def update_variables(self, population):
def update_genes(self, population):
self.population = population
self._update_variables()
self._update_genes()

@abstractmethod
def _update_variables(self):
def _update_genes(self):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class CrossDiversityGeneUpdater(BaseGeneUpdater):
Common variable updater
"""

def _update_variables(self):
def _update_genes(self):
def scale_values(g: Gene, values):
scaled_values = []
if g.min_value == g.max_value:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from math import isnan

import gadapt.utils.ga_utils as ga_utils
from adapters.ga_logging.logging_settings import gadapt_log_error
from gadapt.operations.mutation.chromosome_mutation.random_gene_mutation_rate_determinator import (
RandomGeneMutationRateDeterminator,
)
Expand All @@ -14,18 +17,25 @@ def __init__(
) -> None:
super().__init__()

def _get_mutation_rate(self, genes) -> float:
avg_rsd = ga_utils.average([g.cross_diversity_coefficient for g in genes])
if avg_rsd > 1:
avg_rsd = 1
if avg_rsd < 0:
avg_rsd = 0
return avg_rsd

def _get_number_of_mutation_genes(self) -> int:
genes = [g.gene for g in self.chromosome]
if any(
g.cross_diversity_coefficient is None
or isnan(g.cross_diversity_coefficient)
for g in genes
):
gadapt_log_error("cross_diversity_coefficient not set!")
return super()._get_number_of_mutation_genes()

def get_mutation_rate() -> float:
avg_rsd = ga_utils.average([g.cross_diversity_coefficient for g in genes])
if avg_rsd > 1:
avg_rsd = 1
if avg_rsd < 0:
avg_rsd = 0
return avg_rsd

mutation_rate = get_mutation_rate()
mutation_rate = self._get_mutation_rate(genes)
limit_number_of_mutation_genes = mutation_rate * float(
self.max_number_of_mutation_genes
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import math

import numpy as np

from adapters.ga_logging.logging_settings import gadapt_log_error
from gadapt.operations.mutation.gene_mutation.normal_distribution_gene_mutator import (
NormalDistributionGeneMutator,
)
Expand All @@ -12,6 +15,11 @@ class NormalDistributionCrossDiversityGeneMutator(NormalDistributionGeneMutator)
"""

def _calculate_normal_distribution_standard_deviation(self):
if self.gene_value.gene.cross_diversity_coefficient is None or math.isnan(
self.gene_value.gene.cross_diversity_coefficient
):
gadapt_log_error("cross_diversity_coefficient not set!")
return 0.05
min_std_dev = 0.05
max_std_dev = 0.5
std_dev_range = max_std_dev - min_std_dev
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import math

from adapters.ga_logging.logging_settings import gadapt_log_error
from gadapt.operations.mutation.population_mutation.base_chromosome_mutation_rate_determinator import (
BaseChromosomeMutationRateDeterminator,
)
Expand All @@ -17,21 +18,28 @@ def __init__(
) -> None:
super().__init__()

def _get_cost_diversity_coefficient(self):
cost_diversity_coefficient = float(
self.population.absolute_cost_diversity
/ self.population.absolute_cost_diversity_in_first_population
)
if cost_diversity_coefficient > 1.0:
cost_diversity_coefficient = 1.0
return cost_diversity_coefficient

def _get_mutation_rate(self) -> float:
if (
self.population.absolute_cost_diversity_in_first_population is None
or math.isnan(self.population.absolute_cost_diversity_in_first_population)
or self.population.absolute_cost_diversity is None
or math.isnan(self.population.absolute_cost_diversity)
):
gadapt_log_error("absolute_cost_diversity not set!")
return 1.0
return 1.0 - self._get_cost_diversity_coefficient()

def _get_number_of_mutation_chromosomes(self) -> int:
def get_mutation_rate() -> float:
if (
self.population.average_cost_step_in_first_population is None
or math.isnan(self.population.average_cost_step_in_first_population)
):
return 1.0
cost_step_ratio = float(
self.population.average_cost_step
/ self.population.average_cost_step_in_first_population
)
if cost_step_ratio > 1.0:
cost_step_ratio = 1.0
return 1.0 - cost_step_ratio

mutation_rate = get_mutation_rate()

mutation_rate = self._get_mutation_rate()
f_return_value = mutation_rate * float(self.max_number_of_mutation_chromosomes)
return round(f_return_value)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import random
from math import isnan

from adapters.ga_logging.logging_settings import gadapt_log_error
from gadapt.ga_model.chromosome import Chromosome
from gadapt.operations.mutation.population_mutation.base_chromosome_mutation_rate_determinator import (
BaseChromosomeMutationRateDeterminator,
Expand Down Expand Up @@ -28,18 +30,22 @@ def __init__(
self._sampling = sampling

def _sort_key_parent_diversity_random(self, c: Chromosome):
return (c.parent_diversity, random.random())
return (c.parent_diversity_coefficient, random.random())

def _mutate_population(self):
if self.population is None:
raise Exception("Population must not be null")
unallocated_chromosomes: list[Chromosome] = self._get_unallocated_chromosomes(
self._sort_key_parent_diversity_random
)
if any(isnan(c.parent_diversity_coefficient) for c in unallocated_chromosomes):
gadapt_log_error("parent_diversity_coefficient not set!")
chromosomes_for_mutation: list[Chromosome] = []
if self.population.options.must_mutate_for_same_parents:
chromosomes_for_mutation = [
c for c in unallocated_chromosomes if c.parent_diversity == 0
c
for c in unallocated_chromosomes
if c.parent_diversity_coefficient == 0
]
chromosomes_for_mutation_count = len(chromosomes_for_mutation)
rest_number = (
Expand All @@ -48,14 +54,16 @@ def _mutate_population(self):
if rest_number > 0:
if self.population.options.must_mutate_for_same_parents:
other_chromosomes_for_mutation = [
c for c in unallocated_chromosomes if (not c.parent_diversity == 0)
c
for c in unallocated_chromosomes
if (not c.parent_diversity_coefficient == 0)
]
else:
other_chromosomes_for_mutation = [c for c in unallocated_chromosomes]
other_chromosomes_for_mutation = self._sampling.get_sample(
other_chromosomes_for_mutation,
rest_number,
lambda c: c.parent_diversity,
lambda c: c.parent_diversity_coefficient,
)
chromosomes_for_mutation.extend(other_chromosomes_for_mutation)
for c in chromosomes_for_mutation:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
from abc import ABC, abstractmethod


class BasePopulationUpdater(ABC):
class BasePopulationUpdater:
"""
Base class for population update
"""
Expand All @@ -14,6 +11,5 @@ def update_population(self, population):
self.population = population
self._update_population()

@abstractmethod
def _update_population(self):
pass
Loading

0 comments on commit 5e68d90

Please sign in to comment.