Skip to content

Instantly share code, notes, and snippets.

@dfbarrero
Last active February 23, 2022 17:57
Show Gist options
  • Select an option

  • Save dfbarrero/ea3f81cd9a7847147e48490dd0b44b50 to your computer and use it in GitHub Desktop.

Select an option

Save dfbarrero/ea3f81cd9a7847147e48490dd0b44b50 to your computer and use it in GitHub Desktop.
Genetic Algorithm implemented with Inspyred to solve the one-max problem, with command-line argument parsing. Some evolution statistics are printed in stdout with CSV format, general info is printed in stderr.
""" Genetic Algorithm that solves the one-max problem.
Genetic Algorithm that solves the one-max problem, many parameters in the GA
can be changed by command line. This script has been designed for teaching
GA. Its code is based on the inspyred library examples.
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
"""
from random import Random
from time import time
import inspyred
import argparse
import statistics
import sys
def onemax_fitness(candidates, args):
fitness = []
for cs in candidates:
fit = sum(cs)
fitness.append(fit)
generations = args['_ec'].num_generations
if args['_ec'].num_evaluations > 0:
generations += 1
parsed = args['pararg']
print(",".join(map(str, (args['job'] + 1, generations,
max(fitness), min(fitness),
statistics.mean(fitness), statistics.median(fitness), statistics.stdev(fitness),
parsed.population, parsed.tournament,
parsed.length, parsed.mutation, parsed.crossover))))
return fitness
def generator(random, args):
return [random.choice([0, 1]) for _ in range(args["length"])]
parser = argparse.ArgumentParser(description='One-max problem with a Genetic Algorithms optimizer.')
parser.add_argument('--population', '-p', type=int, metavar='POP', default=30,
help='population size used in the GA [default=30]')
parser.add_argument('--tournament', '-t', type=int, metavar='TOUR', default=2,
help='tournament size [default=2]')
parser.add_argument('--length', '-l', type=int, metavar='SIZE', default=30,
help='chromosome length [default=30]')
parser.add_argument('--generations', '-g', type=int, metavar='GEN', default=20,
help='maximum number of generations to run [default=20]')
parser.add_argument('--crossover', '-c', type=float, metavar='PROB', default=1,
help='crossover probability [default=1]')
parser.add_argument('--mutation', '-m', type=float, metavar='PROB', default=0.01,
help='mutation rate [default=0.01]')
parser.add_argument('--elite', '-e', type=int, metavar='NUM', default=0,
help='elitism size [default=0]')
parser.add_argument('--jobs', '-j', type=int, metavar='JOBS', default=1,
help='number of jobs [default=1]')
args = parser.parse_args()
if (args.mutation > 1):
sys.exit("ERROR: Mutation must be a probability (0 <= pm <= 1)")
if (args.crossover > 1):
sys.exit("ERROR: Crossover must be a probability (0 <= pc <= 1)")
prng = Random()
prng.seed(time())
ea = inspyred.ec.GA(prng)
ea.terminator = inspyred.ec.terminators.generation_termination
ea.selector = inspyred.ec.selectors.tournament_selection
#ea.observer = [inspyred.ec.observers.stats_observer,
# inspyred.ec.observers.plot_observer]
sys.stderr.write(repr(args) + "\n\n")
sys.stderr.flush()
job = 0
print("job,generation,max,min,mean,median,stdev,population,tournament,length,mutation,crossover")
for job in range(args.jobs):
final_pop = ea.evolve(generator=generator,
evaluator=onemax_fitness,
pop_size=args.population,
tournament_size=args.tournament,
max_generations=args.generations,
length=args.length,
mutation_rate=args.mutation,
crossover_rate=args.crossover,
num_elites=args.elite,
pararg=args,
job=job)
best = max(final_pop)
sys.stderr.write('Best solution: \n\t{0}\n'.format(str(best)))
if (best.fitness == args.length):
sys.stderr.write("Solution found!\n")
else:
sys.stderr.write("Solution NOT found\n")
sys.stderr.flush()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment