def plot_bestfitnesses(allfitnesses, outputdir=None): """Create neat plots of fitness evolution of the phenotype with best fitness in every generation.""" if noplotting: print (noplotting) return # create figure fig0 = plt.figure(0, figsize=(7,5)) plt.clf() # get phenotypes with max fitness x = [evolution.get_single_fitnesses(allfitnesses[g]) for g in xrange(len(allfitnesses))] v = [list(x[g].values()) for g in xrange(len(x))] k = [list(x[g].keys()) for g in xrange(len(x))] m = [k[g][v[g].index(max(v[g]))] for g in xrange(len(x))] plt.xlabel("generations") plt.ylabel("fitnesses of best phenotype") widthofline = 1 for f in ["fitnesses"] + allfitnesses[0][0].keys(): if f != "fitnesses": x = [dict((p, allfitnesses[g][p][f]) for p in allfitnesses[g]) for g in xrange(len(allfitnesses))] widthofline = 1 else: widthofline = 2 fitmax = [x[g][m[g]] for g in xrange(len(x))] plt.plot(range(len(fitmax)), fitmax, label=f, linewidth=widthofline) leg = plt.legend(loc='lower right', bbox_to_anchor = (1.05, 1.0)) plt.autoscale(enable=True, axis='x', tight=True) plt.show() if outputdir is not None: plt.savefig(os.path.join(outputdir, "bestfitnesses.png"), bbox_extra_artists=(leg,), bbox_inches='tight')
def plot_allfitnesses(allfitnesses, outputdir=None): """Create neat plots of fitness evolution (both final and partial fitnesses are plotted).""" if noplotting: print noplotting return # create figure fig0 = plt.figure(0, figsize=(7,5)) for f in ["fitnesses"] + allfitnesses[0][0].keys(): if f == "fitnesses": x = [evolution.get_single_fitnesses(allfitnesses[g]) for g in xrange(len(allfitnesses))] else: x = [dict((p, allfitnesses[g][p][f]) for p in allfitnesses[g]) for g in xrange(len(allfitnesses))] # calcuate min/max/avg fitnesses fitmin = [min(x[g].values()) for g in xrange(len(x))] fitmax = [max(x[g].values()) for g in xrange(len(x))] fitavg = [numpy.mean(x[g].values()) for g in xrange(len(x))] fitstd = [numpy.std(x[g].values()) for g in xrange(len(x))] plt.clf() plt.xlabel("generations") plt.ylabel(f) plt.plot(range(len(fitmax)), fitmax, color='r', label="maximum") plt.plot(range(len(fitavg)), fitavg, color='b', label="avg/std") plt.fill_between(range(len(fitavg)), [fitavg[i] - fitstd[i] for i in xrange(len(fitavg))], [fitavg[i] + fitstd[i] for i in xrange(len(fitavg))], edgecolor='b', facecolor='b', alpha=0.2) plt.plot(range(len(fitmin)), fitmin, color='g', label="minimum") plt.legend(loc='lower right') plt.autoscale(enable=True, axis='x', tight=True) plt.show() if outputdir is not None: plt.savefig(os.path.join(outputdir, f + ".png"))
def store_fitnesses(cmaes, fitnesses, solutions): """Forward the fitnesses to the cma object. :param cmaes: the cma evolution strategy object :param fitnesses: multi-objective fitness values of the last generation :param solutions: the solutions generated by the previous cmaes.ask() """ # note that it is a minimizer and we are a maximizer so -1 is needed sfitnesses = evolution.get_single_fitnesses(fitnesses) cmaes.tell(solutions, [-sfitnesses[i] for i in xrange(len(solutions))])
def plot_fitness_as_function_of_pvalue(eparams, allfitnesses, allpvalues, outputdir=None, stability_range=None): """Create a figure showing pvalues and fitness evolution. :param eparams: the evolutionparams python module name :param allfitnesses: allfitnesses[g][p] = dict of multi-objective fitness values for generation g, phenotype p :param allpvalues: allpvalues[g][p][i] = param value of generation g, phenotype p and param index i :param outputdir: directory where the results will be saved :param stability_range: the calculated stability range of the parameters """ if noplotting: print (noplotting) return # get params list params = evolution.get_params_to_evolve(eparams) # get single fitnesses allsfitnesses = [evolution.get_single_fitnesses(allfitnesses[g]) for g in xrange(len(allfitnesses))] # create figure fig0 = plt.figure(0, figsize=(7,5)) for i in xrange(len(params)): plt.clf() plt.xlabel(params[i].name) plt.ylabel("fitness") for g in xrange(len(allsfitnesses)): x = [] y = [] for p in xrange(len(allpvalues[g])): x.append(allpvalues[g][p][i]) y.append(allsfitnesses[g][p]) plt.plot(x, y, 'o', color=plt.cm.jet(float(g)/max(1,(len(allsfitnesses)-1)))) # plot stability range if given if stability_range is not None: for j in range(2): plt.plot([stability_range[i][j], stability_range[i][j]], plt.ylim(), 'k--') # create colorbar for generations if g: ax = fig0.add_axes([0.9, 0.1, 0.03, 0.8]) cmap = plt.cm.jet norm = matplotlib.colors.Normalize(vmin=0, vmax=g) cb = matplotlib.colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='vertical', format='%i') cb.ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(integer=True)) # TODO: this line does not work somehow, why? cb.update_ticks() cb.set_label('generations') # show/save image plt.show() if outputdir is not None: plt.savefig(os.path.join(outputdir, "param__%s.png" % params[i].name))
def init_cma(eparams, lastpvalues=None, fitnesses=None): """Initialize a cma object. :param eparams: the evolutionparams python module name :param lastpvalues: dict of evolvable pvalues for all phenotypes in the last generation. :param fitnesses: dict of multi-objective fitnesses for all phenotypes in the last generation. """ # set params params = evolution.get_params_to_evolve(eparams) n = len(params) opts = { 'bounds': [[0] * n, [1] * n], 'popsize': eparams.phenotypes, 'maxiter': eparams.generations, # 100 + 50 * (N+3)**2 'tolx': 10e-30, # TODO: set it to convenient value } std = 0.5 / 3. # TODO: how to set individual std? Is that possible at all? # initialization with no fitness data if fitnesses is None: # initialization with no pvalues if lastpvalues is None or "mean" not in lastpvalues: return cma.CMAEvolutionStrategy([0.5] * n, std, opts) # initialization with 'mean' pvalues else: # convert mean solution to [0,1] s = [(lastpvalues["mean"][i] - params[i].minv)/(params[i].maxv - params[i].minv) \ if params[i].maxv != params[i].minv else 0.5 for i in xrange(n)] return cma.CMAEvolutionStrategy(s, std, opts) # initialization with previously calculated data else: print( " Warning: initialization with previously partially executed evolution is not optimized yet!" ) print( " std should be calculated from previous data, because now a whole new evolution is started..." ) sfitnesses = evolution.get_single_fitnesses(fitnesses) best = lastpvalues[selection.elite(sfitnesses, 1)[0]] # convert best solution to [0,1] s = [(lastpvalues[best][i] - params[i].minv) / (params[i].maxv - params[i].minv) for i in xrange(n)] return cma.CMAEvolutionStrategy(s, std, opts)
def get_stability_range(eparams, allfitnesses, allpvalues, solution, threshold): """Return main axes of an N dimensional cube in the parameter space inside which all solutions have fitness higher than specified threshold, but not necessarily on the boundary. In other words, find maximal rectangular area of a clearing inside a forest. :param eparams: the evolutionparams python module name :param allfitnesses: allfitnesses[g][p] = dict of multi-objective fitness values for generation g, phenotype p :param allpvalues: allpvalues[g][p][i] = param value of generation g, phenotype p and param index i :param solution: the solution around which we analyse stability :param threshold: fitness threshold above which we treat the system as stable TODO: this version is implemented only for overall/single fitness values TODO: so far only brute force method is used which becomes slow over 5-6 parameter-space dimensions... """ params = evolution.get_params_to_evolve(eparams) allsfitnesses = [evolution.get_single_fitnesses(allfitnesses[g]) for g in xrange(len(allfitnesses))] stability_range = [[params[i].minv, params[i].maxv] for i in xrange(len(params))] # [min, max] center = [(solution[i] - params[i].minv)/(params[i].maxv - params[i].minv) for i in xrange(len(params))] points = [] for g in xrange(len(allfitnesses)): for p in allfitnesses[g]: # skip high fitness points if allsfitnesses[g][p] >= threshold: continue # add normalized point with low fitness to forest list points.append([(allpvalues[g][p][i] - params[i].minv)/(params[i].maxv - params[i].minv) for i in xrange(len(params))]) # get stability range r = get_largest_empty_cube_around_center(center, points) stability_range = get_largest_empty_volume_around_center(center, points, r) # push it back from [0,1] to real parameters space for i in xrange(len(stability_range)): for j in xrange(2): stability_range[i][j] = params[i].minv + stability_range[i][j] * (params[i].maxv - params[i].minv) return stability_range
def plot_fitness_pvalues_animation(eparams, allfitnesses, allpvalues, model=None, x=0, y=1, stability_range=None): """Create an animation showing pvalues and fitness evolution. :param eparams: the evolutionparams python module name :param allfitnesses: allfitnesses[g][p] = dict of multi-objective fitness values for generation g, phenotype p :param allpvalues: allpvalues[g][p][i] = param value of generation g, phenotype p and param index i :param model: the name of the model to get fitness heatmap from (if available) :param x: the first param index to show on the 2D plot :param y: the second param index to show on the 2D plot """ if noplotting: print (noplotting) return # get params list params = evolution.get_params_to_evolve(eparams) # get single fitnesses allsfitnesses = [evolution.get_single_fitnesses(allfitnesses[g]) for g in xrange(len(allfitnesses))] # calcuate min/max/avg fitnesses fitmin = [min(allsfitnesses[g].values()) for g in xrange(len(allsfitnesses))] fitmax = [max(allsfitnesses[g].values()) for g in xrange(len(allsfitnesses))] fitavg = [numpy.mean(allsfitnesses[g].values()) for g in xrange(len(allsfitnesses))] fitstd = [numpy.std(allsfitnesses[g].values()) for g in xrange(len(allsfitnesses))] # initialize animation left window with heatmap of fitness function fig0 = plt.figure(0, figsize=(12,5)) plt.clf() fig0.canvas.set_window_title("Fitness evolution") animleft = fig0.add_subplot(1, 2, 1) animleft.autoscale(enable=True, axis=u'both', tight=True) # draw fitness heatmap if applicable if model is not None: d = 100 X = numpy.linspace(params[x].minv, params[x].maxv, d) Y = numpy.linspace(params[y].maxv, params[y].minv, d) # NOTE: -1x axis direction needed and deliberate Z = [[evolution.get_single_fitness(evolution.get_fitnesses(eparams, model, [[X[i],Y[j]]])[0]) for i in xrange(d)] for j in xrange(d)] animleft.imshow(Z, extent=[params[x].minv, params[x].maxv, params[y].minv, params[y].maxv], interpolation=None) # plot stability range if given if stability_range is not None: animleft.add_patch(Rectangle( xy=[stability_range[x][0], stability_range[y][0]], width=stability_range[x][1] - stability_range[x][0], height=stability_range[y][1] - stability_range[y][0], facecolor='none', edgecolor='k')) # set x-y limits to a slightly larger area than param ranges lag = 0.02 rangex = params[x].maxv - params[x].minv minx = params[x].minv - rangex * lag maxx = params[x].maxv + rangex * lag rangey = params[y].maxv - params[y].minv miny = params[y].minv - rangey * lag maxy = params[y].maxv + rangey * lag plt.xlim([minx, maxx]) plt.ylim([miny, maxy]) # set axis labels plt.xlabel(params[x].name) plt.ylabel(params[y].name) animleft_title = plt.title("generation ##") animleft_dots, = animleft.plot([], [], 'ro') animleft_dotbest, = animleft.plot([], [], 'wo') # initialize animation right window with fitness evolution animright = fig0.add_subplot(1, 2, 2) # animright.autoscale(enable=True, axis=u'both', tight=True) plt.xlabel("generations") plt.ylabel("fitness") animright.plot(range(len(fitmax)), fitmax, color='r', label="maximum") animright.plot(range(len(fitavg)), fitavg, color='b', label="avg/std") animright.fill_between(range(len(fitavg)), [fitavg[i] - fitstd[i] for i in xrange(len(fitavg))], [fitavg[i] + fitstd[i] for i in xrange(len(fitavg))], edgecolor='b', facecolor='b', alpha=0.2) animright.plot(range(len(fitmin)), fitmin, color='g', label="minimum") animright_fitnessline, = animright.plot([], [], 'k--') animright.legend(loc='lower right') # animate generations def animinit(): animleft_title.set_text("") animleft_dots.set_data([], []) animleft_dotbest.set_data([], []) animright_fitnessline.set_data([], []) return animleft_dots, animleft_dotbest, animleft_title, animright_fitnessline def animate(i): animleft_title.set_text("generation #%d" % i) #plt.figure(0) plt.draw() animleft_dots.set_data([allpvalues[i][j][x] for j in xrange(len(allpvalues[i]))], [allpvalues[i][j][y] for j in xrange(len(allpvalues[i]))]) best = sorted(allfitnesses[i], key=allfitnesses[i].get, reverse=True)[0] animleft_dotbest.set_data([allpvalues[i][best][x]], [allpvalues[i][best][y]]) miny = min(plt.yticks()[0]) maxy = max(plt.yticks()[0]) animright_fitnessline.set_data([i,i], [miny, maxy]) return animleft_dots, animleft_dotbest, animleft_title, animright_fitnessline anim = animation.FuncAnimation(fig0, animate, frames = len(allfitnesses), init_func=animinit, interval=200, blit=False) plt.ioff() plt.show()