예제 #1
0
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')
예제 #2
0
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"))
예제 #3
0
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))])
예제 #4
0
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))
예제 #5
0
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)
예제 #6
0
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
예제 #7
0
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()