Merge pull request #10 from danielwilczak101/master

update to be the smae as master
This commit is contained in:
danielwilczak101
2020-10-01 15:54:38 -04:00
committed by GitHub
34 changed files with 250 additions and 153 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

1
CHANGELOG.rst Normal file
View File

@ -0,0 +1 @@

View File

@ -1,19 +0,0 @@
graft docs
graft src
graft ci
graft tests
include .bumpversion.cfg
include .coveragerc
include .cookiecutterrc
include .editorconfig
include AUTHORS.rst
include CHANGELOG.rst
include CONTRIBUTING.rst
include LICENSE
include README.rst
include tox.ini .travis.yml .appveyor.yml .readthedocs.yml .pre-commit-config.yaml
global-exclude *.py[cod] __pycache__/* *.so *.dylib

View File

@ -25,45 +25,7 @@ ga.evolve()
Put the out here
```
## Customized:
```python
import random
import EasyGA
# Setup the default genetic algorithm
ga = EasyGA.GA()
# User set sizes
ga.population_size = 10
ga.chromosome_length = 10
ga.generations = 10
# The user defined gene function
def user_gene_function():
pass
# The user defined Fitness function that gives the chromosome some kind of fitness
def user_fitness_function(chromosome):
pass
# The user defined initialization function
def user_initialization_function():
pass
# User sets the gene function
ga.gene = user_gene_function
# Set the fitness functions
ga.fitness = user_fitness_function
# Changing the initialization function.
ga.initialization = user_initialization_function
# Run the customized genetic algorithm
ga.eveolve()
```
### Output:
```python
Put the out here
```
# How Testing works

View File

@ -1,17 +1,21 @@
from setuptools import setup
from setuptools import setup, find_packages
with open("README.md", "r") as fh:
long_description = fh.read()
setup(
name='EasyGA',
version='0.0.8',
version='0.0.25',
description='A ubiquitous or general purpuse GA',
py_modules=["EasyGA"],
package_dir={'':'src'},
packages=find_packages(where='EasyGA'),
package_dir={
'': 'EasyGA',
},
python_requires='>=3.6',
url="https://github.com/danielwilczak101/EasyGA",
author="Daniel Wilczak",
author="Daniel Wilczak, Jack RyanNguyen, Ryley Griffith, Jared Curtis, Matthew Chase Oxamendi",
author_email="danielwilczak101@gmail.com",
long_description = long_description,
long_description_content_type = "text/markdown",

View File

@ -1,52 +1,111 @@
import random
# Import all the data prebuilt modules
from initialization.population_structure.population import population as create_population
from initialization.chromosome_structure.chromosome import chromosome as create_chromosome
from initialization.gene_structure.gene import gene as create_gene
# Import functionality defaults
from initialization.random_initialization import random_initialization
# Import all the data structure prebuilt modules
from initialization import population as create_population
from initialization import chromosome as create_chromosome
from initialization import gene as create_gene
# Import example classes
from fitness_function import fitness_examples
from initialization import initialization_examples
from termination_point import termination_examples
from selection import selection_examples
from crossover import crossover_examples
from mutation import mutation_examples
class GA:
def __init__(self):
# Default variables
"""Initialize the GA."""
# Initilization variables
self.chromosome_length = 3
self.population_size = 5
self.chromosome_impl = None
self.gene_impl = None
self.population = None
self.generations = 3
self.chromosome_length = 3
self.population_size = 5
# Termination varibles
self.current_generation = 0
self.current_fitness = 0
self.generation_goal = 3
self.fitness_goal = 3
# Mutation variables
self.mutation_rate = 0.03
# Rerun already computed fitness
self.update_fitness = False
# Defualt EastGA implimentation structure
self.initialization_impl = random_initialization
self.initialization_impl = initialization_examples.random_initialization
self.fitness_funciton_impl = fitness_examples.is_it_5
#self.mutation_impl = PerGeneMutation(Mutation_rate)
#self.selection_impl = TournamentSelection()
#self.crossover_impl = FastSinglePointCrossover()
#self.termination_impl = GenerationTermination(Total_generations)
#self.evaluation_impl = TestEvaluation()
self.termination_impl = termination_examples.generation_based
def initialize(self):
def initialize_population(self):
"""Initialize the population using the initialization
implimentation that is currently set"""
self.population = self.initialization_impl(
self.population_size,
self.chromosome_length,
self.chromosome_impl,
self.gene_impl)
def evolve():
# If you just want to evolve through all generations
pass
def get_population_fitness(self,population):
"""Will get and set the fitness of each chromosome in the population.
If update_fitness is set then all fitness values are updated.
Otherwise only fitness values set to None (i.e. uninitialized
fitness values) are updated."""
# Get each chromosome in the population
for chromosome in population:
# If the fitness is not set then get its fitness or if allways getting
# fitness is turn on then always get the fitness of the chromosome.
if(chromosome.fitness == None or self.update_fitness == True):
# Set the chromosomes fitness using the fitness function
chromosome.fitness = self.fitness_funciton_impl(chromosome)
def evolve_generation(self, number_of_generations):
# If you want to evolve through a number of generations
# and be able to pause and output data based on that generation run.
pass
def evolve(self):
"""Runs the ga until the termination point has been satisfied."""
# While the termination point hasnt been reached keep running
while(self.active()):
self.evolve_generation()
def active(self):
"""Returns if the ga should terminate base on the termination implimented"""
# Send termination_impl the whole ga class
return self.termination_impl(self)
def evolve_generation(self, number_of_generations = 1):
"""Evolves the ga the specified number of generations."""
while(number_of_generations > 0):
# If its the first generation then initialize the population
if(self.current_generation == 0):
# Initialize the population
self.initialize_population()
# First get the fitness of the population
self.get_population_fitness(self.population.chromosomes)
# Selection - Triggers flags in the chromosome if its been selected
# self.selection_impl(self)
# Crossover - Takes the flagged chromosomes and crosses there genetic
# makup to make new offsprings.
# self.crossover_impl(self)
# Repopulate - Manipulates the population to some desired way
# self.repopulate_impl(self)
# Mutation - Manipulates the population very slightly
# self.mutation_impl(self)
# Counter for the local number of generations in evolve_generation
number_of_generations -= 1
# Add one to the current overall generation
self.current_generation += 1
def make_gene(self,value):
"""Let's the user create a gene."""
return create_gene(value)
def make_chromosome(self):
"""Let's the user create a chromosome."""
return create_chromosome()
def make_population(self):
"""Let's the user create a population."""
return create_population()

3
src/__init__.py Normal file
View File

@ -0,0 +1,3 @@
import EasyGA
import run_testing
import test_EasyGA

View File

@ -0,0 +1,2 @@
# FROM (. means local) file_name IMPORT function_name
from .examples import crossover_examples

15
src/crossover/examples.py Normal file
View File

@ -0,0 +1,15 @@
class crossover_examples:
""" Crossover explination goes here.
Points - Defined as sections between the chromosomes genetic makeup
"""
def single_point_crossover(ga):
"""Single point crossover is when a "point" is selected and the genetic
make up of the two parent chromosomes are "Crossed" or better known as swapped"""
pass
def multi_point_crossover(ga,number_of_points = 2):
"""Multi point crossover is when a specific number (More then one) of
"points" are created to merge the genetic makup of the chromosomes."""
pass

View File

@ -0,0 +1,2 @@
# FROM (. means local) file_name IMPORT class name
from .examples import fitness_examples

View File

@ -0,0 +1,16 @@
class fitness_examples:
"""Fitness function examples used"""
def is_it_5(chromosome):
"""A very simple case test function - If the chromosomes gene value is a 5 add one
to the chromosomes overall fitness value."""
# Overall fitness value
fitness = 0
# For each gene in the chromosome
for gene in chromosome.genes:
# Check if its value = 5
if(gene.value == 5):
# If its value is 5 then add one to
# the overal fitness of the chromosome.
fitness += 1
return fitness

View File

@ -0,0 +1,5 @@
# FROM (. means local) file_name IMPORT function_name
from .examples import initialization_examples
from .population_structure.population import population
from .chromosome_structure.chromosome import chromosome
from .gene_structure.gene import gene

View File

@ -1,37 +1,48 @@
class chromosome:
# fitness = Empty; genes = [gene, gene, gene, etc.]
def __init__(self, genes = None):
"""Initialize the chromosome based on input gene list, defaulted to an empty list"""
if genes is None:
self.genes = []
else:
self.genes = genes
# The fitness of the overal chromosome
self.fitness = None
# If the chromosome has been selected then the flag would switch to true
self.selected = False
def add_gene(self, gene, index = -1):
"""Add a gene to the chromosome at the specified index, defaulted to end of the chromosome"""
if index == -1:
index = len(self.genes)
self.genes.insert(index, gene)
def remove_gene(self, index):
"""Remove a gene from the chromosome at the specified index"""
del self.genes[index]
def get_genes(self):
"""Return all genes in the chromosome"""
return self.genes
def get_fitness(self):
"""Return the fitness of the chromosome"""
return self.fitness
def set_gene(self, gene, index):
"""Set a gene at a specific index"""
self.genes[index] = gene
def set_genes(self, genes):
"""Set the entire gene set of the chromosome"""
self.genes = genes
def set_fitness(self, fitness):
"""Set the fitness value of the chromosome"""
self.fitness = fitness
def __repr__(self):
"""Format the repr() output for the chromosome"""
output_str = ''
for gene in self.genes:
output_str += gene.__repr__()

View File

@ -0,0 +1,33 @@
# Import the data structure
from .population_structure.population import population as create_population
from .chromosome_structure.chromosome import chromosome as create_chromosome
from .gene_structure.gene import gene as create_gene
class initialization_examples:
"""Initialization examples that are used as defaults and examples"""
def random_initialization(population_size, chromosome_length, chromosome_impl, gene_impl):
"""Takes the initialization inputs and choregraphs them to output the type of population
with the given parameters."""
# Create the population object
population = create_population()
# Fill the population with chromosomes
for i in range(population_size):
chromosome = create_chromosome()
#Fill the Chromosome with genes
for j in range(chromosome_length):
# Using the chromosome_impl to set every index inside of the chromosome
if chromosome_impl != None:
# Each chromosome location is specified with its own function
chromosome.add_gene(create_gene(chromosome_impl(j)))
# Will break if chromosome_length != len(lists) in domain
elif gene_impl != None:
# gene_impl = [range function,lowerbound,upperbound]
function = gene_impl[0]
chromosome.add_gene(create_gene(function(*gene_impl[1:])))
else:
#Exit because either were not specified
print("Your domain or range were not specified")
population.add_chromosome(chromosome)
return population

View File

@ -1,16 +0,0 @@
# Import the data structure
from .population_structure.population import population as create_population
from .chromosome_structure.chromosome import chromosome as create_chromosome
from .gene_structure.gene import gene as create_gene
def focused_initialization(chromosome_length,population_size,gene_function):
# Create the population object
population = create_population()
# Fill the population with chromosomes
for i in range(population_size):
chromosome = create_chromosome()
#Fill the Chromosome with genes
for j in range(chromosome_length):
chromosome.add_gene(create_gene(gene_function()))
population.add_chromosome(chromosome)
return population

View File

@ -4,21 +4,28 @@ def check_gene(value):
return value
class gene:
def __init__(self, value):
"""Initialize a gene with fitness of value None and the input value"""
self.fitness = None
self.value = check_gene(value)
def get_fitness(self):
"""Return fitness of the gene"""
return self.fitness
def get_value(self):
"""Return value of the gene"""
return self.value
def set_fitness(self, fitness):
"""Set fitness of the gene"""
self.fitness = fitness
def set_value(self):
"""Set value of the gene"""
self.value = value
def __repr__(self):
"""Format the repr() output value"""
return f'[{self.value}]'

View File

@ -1,7 +1,7 @@
class population:
# fitness = Empty; population = [chromosome, chromosome, etc.]
def __init__(self, chromosomes = None):
"""Intiialize the population with fitness of value None, and a set of chromosomes dependant on user-passed parameter"""
if chromosomes is None:
self.chromosomes = []
else:
@ -9,47 +9,48 @@ class population:
self.fitness = None
def get_closet_fitness(self,value):
# Get the chomosome that has the closets fitness to the value defined
"""Get the chomosome that has the closets fitness to the value defined"""
pass
def add_chromosome(self, chromosome, index = -1):
"""Adds a chromosome to the population at the input index, defaulted to the end of the chromosome set"""
if index == -1:
index = len(self.chromosomes)
self.chromosomes.insert(index, chromosome)
def remove_chromosome(self, index):
"""removes a chromosome from the indicated index"""
del self.chromosomes[index]
def get_all_chromosomes(self):
"""returns all chromosomes in the population"""
return chromosomes
def get_fitness(self):
"""returns the population's fitness"""
return self.fitness
def set_all_chromosomes(self, chromosomes):
"""sets the chromosome set of the population"""
self.chromosomes = chromosomes
def set_chromosome(self, chromosomes, index):
self.chromosome[index] = chromosome
def set_chromosome(self, chromosome, index):
"""sets a specific chromosome at a specific index"""
self.chromosomes[index] = chromosome
def set_fitness(self, fitness):
"""Sets the fitness value of the population"""
self.fitness = fitness
def __repr__(self):
"""Sets the repr() output format"""
return ''.join([chromosome.__repr__() for chromosome in self.chromosomes])
def print_all(self):
# Ex .Current population
# Chromosome 1 - [gene][gene][gene][.etc] / Chromosome fitness - #
"""Prints information about the population in the following format:"""
"""Ex .Current population"""
"""Chromosome 1 - [gene][gene][gene][.etc] / Chromosome fitness - """
print("Current population:")
for index in range(len(self.chromosomes)):
print(f'Chromosome - {index} {self.chromosomes[index]}', end = "")
print(f' / Fitness = {self.chromosomes[index].fitness}')
def generate_first_chromosomes(self, chromosome_count, chromosome_length, gene_lower_bound, gene_upper_bound):
#Creating the chromosomes with Genes of random size
for x in range(chromosome_count):
chromosome = Chromosome(chromosome_length)
for y in range(chromosome_length):
chromosome.gene_set[y] = Gene(random.randint(gene_lower_bound[y], gene_upper_bound[y]))
self.chromosome_set.append(chromosome)

View File

@ -1,26 +0,0 @@
# Import the data structure
from .population_structure.population import population as create_population
from .chromosome_structure.chromosome import chromosome as create_chromosome
from .gene_structure.gene import gene as create_gene
def random_initialization(population_size, chromosome_length, chromosome_impl, gene_impl):
# Create the population object
population = create_population()
# Fill the population with chromosomes
for i in range(population_size):
chromosome = create_chromosome()
#Fill the Chromosome with genes
for j in range(chromosome_length):
if chromosome_impl != None:
# Each chromosome location is specified with its own function
chromosome.add_gene(create_gene(chromosome_impl(j)))
# Will break if chromosome_length != lists in domain
elif gene_impl != None:
# gene_impl = [range function,lowerbound,upperbound]
function = gene_impl[0]
chromosome.add_gene(create_gene(function(gene_impl[1],gene_impl[2])))
else:
#Exit because either were not specified
print("Your domain or range were not specified")
population.add_chromosome(chromosome)
return population

View File

2
src/mutation/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# FROM (. means local) file_name IMPORT function_name
from .examples import mutation_examples

3
src/mutation/examples.py Normal file
View File

@ -0,0 +1,3 @@
class mutation_examples:
"""Selection examples will go here """
pass

View File

View File

@ -3,18 +3,15 @@ import random
# Create the Genetic algorithm
ga = EasyGA.GA()
def user_gene_domain(gene_index):
"""Each gene index is assosiated to its index in the chromosome"""
chromosome = [
random.randrange(1,100),
random.uniform(10,5),
random.choice(["up","down"])
]
return chromosome[gene_index]
ga.chromosome_length = 3
ga.max_generations = 5
# If the user wants to use a domain
ga.chromosome_impl = user_gene_domain
ga.gene_impl = [random.randrange,1,10]
ga.initialize()
ga.generation = 36
# Run Everyhting
ga.evolve()
# Print the current population
ga.population.print_all()

View File

@ -0,0 +1,2 @@
# FROM (. means local) file_name IMPORT function_name
from .examples import selection_examples

15
src/selection/examples.py Normal file
View File

@ -0,0 +1,15 @@
class selection_examples:
"""Selection defintion here"""
def tournament_selection():
""" """
pass
def roulette_selection():
"""Roulette selection works based off of how strong the fitness is of the
chromosomes in the population. The stronger the fitness the higher the probability
that it will be selected. Using the example of a casino roulette wheel.
Where the chromosomes are the numbers to be selected and the board size for
those numbers are directly proportional to the chromosome's current fitness. Where
the ball falls is a randomly generated number between 0 and 1"""
pass

View File

View File

@ -0,0 +1,2 @@
# FROM (. means local) file_name IMPORT class name
from .examples import termination_examples

View File

@ -0,0 +1,16 @@
class termination_examples:
"""Example functions that can be used to terminate the the algorithms loop"""
def fitness_based(ga):
"""Fitness based approach to terminate when the goal fitness has been reached"""
status = True
if(ga.current_fitness > ga.fitness_goal):
status = False
return status
def generation_based(ga):
"""Generation based approach to terminate when the goal generation has been reached"""
status = True
if(ga.current_generation > ga.generation_goal):
status = False
return status

View File