Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Alexander R. Hankin
EE194_Manduca_Simulator
Commits
616db72d
Commit
616db72d
authored
May 09, 2018
by
Alexander R. Hankin
Browse files
added example usages for Manducas.py and Popoulation.py
parent
d96402f7
Changes
2
Hide whitespace changes
Inline
Side-by-side
manduca/Manducas.py
View file @
616db72d
"""
Example Usage:
Return a random Manduca in a function
>>> num_legs, time_segments, time_step = 2, 4, 10
>>>
>>> def random_manduca():
>>> return SimpleManduca.random_individual(num_legs, time_segments, time_step)
"""
import
types
import
numpy
as
np
from
scipy.integrate
import
odeint
...
...
manduca/Population.py
View file @
616db72d
"""
Example Usage:
Create an evolution simulator and run simulation for 25 generations using a pool of threads:
>>> POPULATION_SIZE, NUM_GENERATIONS= 10, 25
>>> try:
>>> pool = multiprocessing.Pool(int(multiprocessing.cpu_count()))
>>> simulator = EvolutionSimulator((random_manduca, POPULATION_SIZE), pool=pool)
>>> simulator.run_simulation(NUM_GENERATIONS)
>>> finally:
>>> pool.close()
"""
import
numpy
as
np
import
copy
import
tqdm
from
collections
import
namedtuple
class
GenerationInfo
(
namedtuple
(
'GenerationInfo'
,
[
'generation_number'
,
'fitness_values'
,
'surviving_ancestors'
,
'surviving_children'
,
'surviving_mutants'
,
...
...
@@ -11,28 +28,62 @@ class GenerationInfo(namedtuple('GenerationInfo', ['generation_number', 'fitness
'duplicate_children'
,
'duplicate_mutants'
])):
@
property
def
max_fitness
(
self
):
"""This function gets the maximum fitness value in a generation of Manducas
:returns: float -- the max fitness value
"""
return
max
(
self
.
fitness_values
)
@
property
def
child_survival_rate
(
self
):
if
self
.
num_matings
is
None
:
return
None
return
float
(
self
.
surviving_children
)
/
self
.
num_matings
"""This function computes the survival rate for Manduca children
:returns: float -- the child survival rate.
"""
if
self
.
num_matings
is
None
:
return
None
return
float
(
self
.
surviving_children
)
/
self
.
num_matings
@
property
def
mutant_survival_rate
(
self
):
if
self
.
num_mutants
is
None
:
return
None
return
float
(
self
.
surviving_mutants
)
/
self
.
num_mutants
"""This function computes the survival rate for Manduca mutants
:returns: float -- the mutant survival rate.
"""
if
self
.
num_mutants
is
None
:
return
None
return
float
(
self
.
surviving_mutants
)
/
self
.
num_mutants
@
property
def
parent_survival_rate
(
self
):
if
self
.
num_ancestors
is
None
:
return
None
return
float
(
self
.
surviving_ancestors
)
/
self
.
num_ancestors
"""This function computes the survival rate for Manduca parents
:returns: float -- the parent survival rate.
"""
if
self
.
num_ancestors
is
None
:
return
None
return
float
(
self
.
surviving_ancestors
)
/
self
.
num_ancestors
class
EvolutionParameters
(
object
):
def
__init__
(
self
,
max_population
,
num_matings
,
num_mutants
,
max_mutations
,
**
kwargs
):
"""This function is the constructor for the EvolutionParameters class
:param max_population: The maximum population size.
:type max_population: int.
:param num_matings: The number of matings.
:type num_matings: int.
:param num_mutants: The number of mutants.
:type num_mutants: int.
:param max_mutations: The maximum number of mutations that can happen.
:type max_mutations: int.
"""
self
.
max_population
=
max_population
self
.
num_matings
=
num_matings
self
.
num_mutants
=
num_mutants
...
...
@@ -41,13 +92,27 @@ class EvolutionParameters(object):
self
.
num_random
=
kwargs
.
pop
(
'num_random'
,
int
(
self
.
max_population
/
20.0
))
def
update_parameters
(
self
,
history
):
"""Basic EvolutionParameters doesn't change as the simulation progresses"""
"""
This function updates basic EvolutionParameters.
Basic EvolutionParameters doesn't change as the simulation progresses"""
pass
class
EvolutionSimulator
(
object
):
default_evolution_parameters
=
EvolutionParameters
(
20
,
10
,
10
,
10
)
def
__init__
(
self
,
population
,
evolution_parameters
=
None
,
random_number_generator
=
None
,
random_seed
=
None
,
pool
=
None
):
"""This function is the constructor for the EvolutionSimulator class
:param population: A list of Manducas or a function that produces a new random Manduca.
:type population: list or function.
:param evolution_parameters: Extra evolution parameters.
:type evolution_parameters: EvolutionParameters.
:param random_number_generator: The type of random number generator.
:type random_number_generator: A random number generator.
:param random_seed: A random seed for the random number generator.
:type random_seed: int.
:param pool: A pool of processes to simulate in parallel using multiprocessing.
:type pool: multiprocessing.Pool.
"""
"""Population can be array of manducas or tuple of (f, num_pop), where each call to f()
produces a member of the population"""
if
evolution_parameters
is
None
:
...
...
@@ -82,9 +147,21 @@ class EvolutionSimulator(object):
@
property
def
current_fitnesses
(
self
):
"""This function gets the current fitnesses for the current generation.
:returns: float -- the array of fitnesses.
"""
return
sorted
([
m
.
fitness
for
m
in
self
.
population
],
reverse
=
True
)
def
next_generation
(
self
,
current_generation
):
"""This function generates the next generation of Manducas.
:param current_generation: Used for logging purposes.
:type current_generation: int.
:returns: GenerationInfo -- a summary of the generation.
"""
# mate: create children of two random parents
self
.
mate
()
# mutate: create mutations of random individuals
...
...
@@ -123,9 +200,17 @@ class EvolutionSimulator(object):
@
property
def
population_size
(
self
):
"""This function returns the size of the population
:returns: int -- the population size.
"""
return
len
(
self
.
population
)
def
mate
(
self
):
"""This function performs the mating for the generation.
"""
self
.
_children
=
[]
rng
=
self
.
random_number_generator
for
_
in
range
(
self
.
evolution_parameters
.
num_matings
):
...
...
@@ -134,6 +219,10 @@ class EvolutionSimulator(object):
self
.
_children
.
append
(
p1
.
mate
(
p2
,
rng
=
rng
))
def
mutate
(
self
):
"""This function performs the mutations for the generation.
"""
self
.
_mutants
=
[]
for
_
in
range
(
self
.
evolution_parameters
.
num_mutants
):
rng
=
self
.
random_number_generator
...
...
@@ -142,6 +231,11 @@ class EvolutionSimulator(object):
self
.
_mutants
.
append
(
clone
)
def
survive
(
self
):
"""This function keeps the best 10 individuals as well as some random individuals weighted by fitness.
:returns: int -- the number of Manducas left
"""
rng
=
self
.
random_number_generator
all_manducas
=
[(
m
,
0
)
for
m
in
self
.
population
]
+
\
...
...
@@ -186,6 +280,16 @@ class EvolutionSimulator(object):
return
num_after_survival
def
run_simulation
(
self
,
num_generations
,
history_interval
=
1
,
progress_bar
=
True
):
"""This function runs the genetic algorithm simulation
:param num_generations: The number of generations.
:type num_generations: int.
:param history_interval: The amount of years to skip between saved histories.
:type history_interval: int.
:param progress_bar: Whether to display the progress.
:type progress_bar: bool.
"""
progress_kwargs
=
{
'disable'
:
not
(
progress_bar
),
'desc'
:
'Genetic Algorithm Simulation'
,
'unit'
:
'gen'
}
for
generation
in
tqdm
.
tqdm
(
range
(
num_generations
),
**
progress_kwargs
):
generation_info
=
self
.
next_generation
(
generation
)
...
...
@@ -194,10 +298,18 @@ class EvolutionSimulator(object):
@
property
def
max_fitness
(
self
):
"""This function returns the maximum fitness value for all Manducas in the generation.
:returns: float -- the maximum fitness.
"""
all_manducas
=
self
.
population
+
self
.
_children
+
self
.
_mutants
return
max
([
manduca
.
fitness
for
manduca
in
all_manducas
])
def
update_fitness
(
self
):
"""This function sets the fitnesses for a generation of Manducas
"""
all_manducas
=
self
.
population
+
self
.
_children
+
self
.
_mutants
if
self
.
pool
is
not
None
:
# Don't bother sending manducas that already have _fitness saved
...
...
@@ -208,4 +320,11 @@ class EvolutionSimulator(object):
[
manduca
.
fitness
for
manduca
in
all_manducas
]
def
compute_fitness
(
manduca
):
return
manduca
.
fitness
"""This function gets the fitness value of a Manduca
:param manduca: The Manduca who's fitness is returned.
:type manduca: Manduca.
:returns: float -- the fitness value.
"""
return
manduca
.
fitness
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment