Proper repr implementations, improved index_of method, and improved initialization
- Repr now supports reversal using eval i.e. obj == eval(repr(obj)) for any data object. This assumes a GA object called ga. - Index of now supports local searching if an estimate of the index is given. - Initialization of data objects is now easier and works for any iterable input e.g. ga.make_chromosome
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
from copy import deepcopy
|
||||
from structure import Gene as make_gene
|
||||
|
||||
class Chromosome:
|
||||
|
||||
@ -6,7 +6,7 @@ class Chromosome:
|
||||
"""Initialize the chromosome with fitness value of None, and a
|
||||
set of genes dependent on user-passed parameter."""
|
||||
|
||||
self.gene_list = [deepcopy(gene) for gene in gene_list]
|
||||
self.gene_list = [make_gene(gene) for gene in gene_list]
|
||||
self.fitness = None
|
||||
|
||||
|
||||
@ -70,6 +70,15 @@ class Chromosome:
|
||||
self.gene_list[index] = gene
|
||||
|
||||
|
||||
def __delitem__(self, index):
|
||||
"""
|
||||
Allows the user to use
|
||||
del chromosome[index]
|
||||
to delete a gene at the specified index.
|
||||
"""
|
||||
del self.gene_list[index]
|
||||
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
Allows the user to use
|
||||
@ -88,16 +97,41 @@ class Chromosome:
|
||||
return (searched_gene in self.gene_list)
|
||||
|
||||
|
||||
def index_of(self, searched_gene):
|
||||
def index_of(self, gene, guess = None):
|
||||
"""
|
||||
Allows the user to use
|
||||
index = chromosome.index_of(gene)
|
||||
index = chromosome.index_of(gene, guess)
|
||||
to find the index of a gene in the chromosome.
|
||||
Be sure to check if the chromosome contains the gene
|
||||
first, or to catch an exception if the gene is not
|
||||
in the chromosome.
|
||||
first, or to catch an IndexError exception if the gene
|
||||
is not in the chromosome. A guess may be used to find
|
||||
the index quicker.
|
||||
"""
|
||||
return self.gene_list.index(searched_gene)
|
||||
|
||||
# Use built-in method
|
||||
if guess is None:
|
||||
return self.gene_list.index(gene)
|
||||
|
||||
# Use symmetric mod
|
||||
guess %= len(self)
|
||||
if guess >= len(self)//2:
|
||||
guess -= len(self)
|
||||
|
||||
# Search outwards for the gene
|
||||
for i in range(1+len(self)//2):
|
||||
|
||||
# Search to the left
|
||||
if gene == self[guess-i]:
|
||||
return (guess-i) % len(self)
|
||||
|
||||
# Search to the right
|
||||
elif gene == self[guess+i]:
|
||||
return (guess+i) % len(self)
|
||||
|
||||
# Gene not found
|
||||
else:
|
||||
raise IndexError("No such gene in the chromosome found")
|
||||
|
||||
|
||||
def __eq__(self, chromosome):
|
||||
@ -107,17 +141,19 @@ class Chromosome:
|
||||
chromosome_1 != chromosome_2
|
||||
to compare two chromosomes based on their genes.
|
||||
"""
|
||||
|
||||
return all(gene_1 == gene_2 for gene_1, gene_2 in zip(self, chromosome))
|
||||
return self.gene_list == chromosome.gene_list
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Allows the user to use
|
||||
repr(chromosome)
|
||||
to get a backend representation of the chromosome.
|
||||
chromosome_string = repr(chromosome)
|
||||
chromosome = eval(chromosome_string)
|
||||
to get a backend representation of the chromosome
|
||||
which can be evaluated directly as code to create
|
||||
the chromosome.
|
||||
"""
|
||||
return ', '.join(repr(gene) for gene in self)
|
||||
return f"EasyGA.make_chromosome({repr(self.gene_list)})"
|
||||
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -3,8 +3,15 @@ from copy import deepcopy
|
||||
class Gene:
|
||||
|
||||
def __init__(self, value):
|
||||
"""Initialize a gene with fitness of value None and the input value."""
|
||||
self.value = deepcopy(value)
|
||||
"""Initialize a gene with the input value."""
|
||||
|
||||
# Copy another gene
|
||||
try:
|
||||
self.value = deepcopy(value.value)
|
||||
|
||||
# Otherwise copy the given value
|
||||
except:
|
||||
self.value = deepcopy(value)
|
||||
|
||||
|
||||
def __eq__(self, other_gene):
|
||||
@ -20,10 +27,11 @@ class Gene:
|
||||
def __repr__(self):
|
||||
"""
|
||||
Allows the user to use
|
||||
repr(gene)
|
||||
gene_string = repr(gene)
|
||||
gene = eval(gene_string)
|
||||
to get a backend representation of the gene.
|
||||
"""
|
||||
return str(self.value)
|
||||
return f"EasyGA.make_gene({repr(self.value)})"
|
||||
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
from copy import deepcopy
|
||||
from structure import Chromosome as make_chromosome
|
||||
|
||||
class Population:
|
||||
|
||||
def __init__(self, chromosome_list):
|
||||
"""Initialize the population with fitness of value None, and a
|
||||
set of chromosomes dependant on user-passed parameter."""
|
||||
"""Initialize the population with a collection
|
||||
of chromosomes dependant on user-passed parameter."""
|
||||
|
||||
self.chromosome_list = [deepcopy(chromosome) for chromosome in chromosome_list]
|
||||
self.fitness = None
|
||||
self.chromosome_list = [make_chromosome(chromosome) for chromosome in chromosome_list]
|
||||
self.mating_pool = []
|
||||
self.next_population = []
|
||||
|
||||
@ -135,25 +134,61 @@ class Population:
|
||||
return (searched_chromosome in self.chromosome_list)
|
||||
|
||||
|
||||
def index_of(self, searched_chromosome):
|
||||
def index_of(self, chromosome, guess = None):
|
||||
"""
|
||||
Allows the user to use
|
||||
index = population.index_of(chromosome)
|
||||
index = population.index_of(chromosome, guess)
|
||||
to find the index of a chromosome in the population.
|
||||
Be sure to check if the population contains the chromosome
|
||||
first, or to catch an exception if the chromosome is not
|
||||
in the population.
|
||||
first, or to catch an IndexError exception if the chromosome
|
||||
is not in the population. A guess may be used to find the
|
||||
index quicker.
|
||||
"""
|
||||
return self.chromosome_list.index(searched_chromosome)
|
||||
|
||||
# Use built-in method
|
||||
if guess is None:
|
||||
return self.chromosome_list.index(gene)
|
||||
|
||||
# Use symmetric mod
|
||||
guess %= len(self)
|
||||
if guess >= len(self)//2:
|
||||
guess -= len(self)
|
||||
|
||||
# Search outwards for the gene
|
||||
for i in range(len(self)//2):
|
||||
|
||||
# Search to the left
|
||||
if chromosome == self[guess-i]:
|
||||
return (guess-i) % len(self)
|
||||
|
||||
# Search to the right
|
||||
elif chromosome == self[guess+i]:
|
||||
return (guess+i) % len(self)
|
||||
|
||||
# Gene not found
|
||||
else:
|
||||
raise IndexError("No such chromosome in the population found")
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Allows the user to use
|
||||
repr(population)
|
||||
population_string = repr(population)
|
||||
population = eval(population_string)
|
||||
to get a backend representation of the population
|
||||
which can be evaluated directly as code to create
|
||||
the population.
|
||||
"""
|
||||
return "EasyGA.make_population({repr(self.chromosome_list)})"
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Allows the user to use
|
||||
str(population)
|
||||
print(population)
|
||||
to get a backend representation of the population.
|
||||
to get a frontend representation of the population.
|
||||
"""
|
||||
return ''.join(
|
||||
f'Chromosome - {index} {chromosome} / Fitness = {chromosome.fitness}\n'
|
||||
|
||||
Reference in New Issue
Block a user