import argparse import os import sys import numpy as np #TODO add new example: steadystate.py (analogous to standard.py) #TODO extend both standard.py and steadystate.py to support >1 criteria (using DEAP's selNSGA2() and selSPEA2()) #TODO add comments to all examples in this directory #TODO add to standard.py and steadystate.py evaluating each genotype in HOF N (configurable, default 10) times when the evolution ends #TODO protect all examples against invalid genotypes (fill population until all genotypes are conrrectly evaluated). And maybe remove invalid.py if it overlaps with (is a subset of) other examples from FramsticksLib import FramsticksLib from evolalg.base.lambda_step import LambdaStep from evolalg.dissimilarity.frams_dissimilarity import FramsDissimilarity from evolalg.experiment import Experiment from evolalg.fitness.fitness_step import FitnessStep from evolalg.mutation_cross.frams_cross_and_mutate import FramsCrossAndMutate from evolalg.population.frams_population import FramsPopulation from evolalg.selection.tournament import TournamentSelection from evolalg.statistics.halloffame_stats import HallOfFameStatistics from evolalg.statistics.statistics_deap import StatisticsDeap from evolalg.base.union_step import UnionStep def ensureDir(string): if os.path.isdir(string): return string else: raise NotADirectoryError(string) def parseArguments(): parser = argparse.ArgumentParser( description='Run this program with "python -u %s" if you want to disable buffering of its output.' % sys.argv[ 0]) parser.add_argument('-path', type=ensureDir, required=True, help='Path to Framsticks without trailing slash.') parser.add_argument('-opt', required=True, help='optimization criteria : vertpos, velocity, distance, vertvel, lifespan, numjoints, numparts, numneurons, numconnections. Single or multiple criteria.') parser.add_argument('-lib', required=False, help="Filename of .so or .dll with framsticks library") parser.add_argument('-genformat', required=False, default="1", help='Genetic format for the demo run, for example 4, 9, or B. If not given, f1 is assumed.') parser.add_argument("-popsize", type=int, default=50, help="Size of population, default 50.") return parser.parse_args() def extract_fitness(ind): return ind.fitness def print_population_count(pop): print("Current:", len(pop)) return pop # Each step must return a population def main(): parsed_args = parseArguments() frams = FramsticksLib(parsed_args.path, parsed_args.lib, "eval-allcriteria.sim") hall_of_fame = HallOfFameStatistics(100, "fitness") statistics_union = UnionStep([ hall_of_fame, StatisticsDeap([ ("avg", np.mean), ("stddev", np.std), ("min", np.min), ("max", np.max), ("count", len) ], extract_fitness) ]) fitness = FitnessStep(frams, fields={parsed_args.opt: "fitness", }, fields_defaults={}) init_stages = [FramsPopulation(frams, parsed_args.genformat, 50), fitness, statistics_union] selection = TournamentSelection(5, copy=True, fit_attr="fitness") new_generation_steps = [ FramsCrossAndMutate(frams, cross_prob=0.2, mutate_prob=0.9), fitness, ] generation_modifications = [ statistics_union ] experiment = Experiment(init_population=init_stages, selection=selection, new_generation_steps=new_generation_steps, generation_modification=generation_modifications, end_steps=[], population_size=parsed_args.popsize ) experiment.init() experiment.run(3) for ind in hall_of_fame.haloffame: print("%g\t%s" % (ind.fitness, ind.genotype)) if __name__ == '__main__': main()