1- # Genetic Algorithms
1+ # Genetic Algorithm (GA)
2+
3+ from typing import Callable , Optional , Sequence , Tuple
24
3- from typing import Optional , Callable , Sequence , Tuple
45import numpy as np
6+ from plotly import express as px
7+ from rich .console import Console
58from rich .progress import Progress
69from rich .table import Table
7- from rich .console import Console
8- from plotly import express as px
910
10- from . utils import Population , Encoding
11+ from metazoo . bio . utils import Encoding , Population
1112
1213
1314class GeneticAlgorithm :
1415 """A Simple Genetic Algorithm (GA) implementation."""
16+
1517 def __init__ (
1618 self ,
1719 fitness_function : Callable [[np .ndarray ], float ],
@@ -54,16 +56,16 @@ def summary(self):
5456 table .add_row ("Genome Length" , str (self .genome_length ))
5557 table .add_row ("Mutation Rate" , str (self .mutation_rate ))
5658 table .add_row ("Crossover Rate" , str (self .crossover_rate ))
57- #table.add_row("Encoding", str(self.encoding))
59+ # table.add_row("Encoding", str(self.encoding))
5860 table .add_row ("Selection Function" , self .selection_function .__name__ )
5961 table .add_row ("Crossover Function" , self .crossover_function .__name__ )
6062 table .add_row ("Mutation Function" , self .mutation_function .__name__ )
6163 table .add_row ("Fitness Function" , self .fitness_function .__name__ )
62- #table.add_row("Dimension", str(self.dim))
64+ # table.add_row("Dimension", str(self.dim))
6365 table .add_row (
6466 "Elitism" , str (self .elitism ) if self .elitism is not None else "None"
6567 )
66- #if self.encoding == "binary":
68+ # if self.encoding == "binary":
6769 # table.add_row("Epsilon", str(self.epsilon))
6870 # table.add_row("Bits Per Var", str(self.bits_per_var))
6971 # table.add_row("Genome Length", str(self.genome_length))
@@ -76,7 +78,7 @@ def eval(self):
7678 """
7779 Evaluate the fitness of the current population.
7880 """
79-
81+
8082 # Raw Fitness.
8183
8284 raw_fitness = np .array (
@@ -109,7 +111,9 @@ def evolve(self):
109111 fitness , fitness_transformed = self .eval ()
110112 self .fitness_history .append (fitness .mean ())
111113 self .best_history .append (self .best_fitness )
112- selected_indices = self .selection_function (self .population .individuals , fitness_transformed )
114+ selected_indices = self .selection_function (
115+ self .population .individuals , fitness_transformed
116+ )
113117 selected_parents = self .population .individuals [selected_indices ]
114118 next_generation = self .create_descendants (selected_parents )
115119
@@ -177,7 +181,10 @@ def run(
177181 pop_history .append (self .population .individuals .copy ())
178182 best_history .append (self .best_individual )
179183 if history :
180- pop_history = [[self .population .encoding .decode (ind ) for ind in gen ] for gen in pop_history ]
184+ pop_history = [
185+ [self .population .encoding .decode (ind ) for ind in gen ]
186+ for gen in pop_history
187+ ]
181188 return (best_history , pop_history )
182189
183190 def fitness_plot (self , best = False ) -> None :
@@ -195,6 +202,6 @@ def fitness_plot(self, best=False) -> None:
195202 labels = {"x" : "Generation" , "y" : "Best Fitness" },
196203 title = "Best Fitness History" ,
197204 )
198- return fig
205+ return fig
199206 else :
200207 raise ValueError ("No fitness history to plot. Run the algorithm first." )
0 commit comments