Exemplo n.º 1
0
def sel_nsga_iii(individuals, k):
    '''Implements NSGA-III selection as described in
    Deb, K., & Jain, H. (2014). An Evolutionary Many-Objective Optimization
    Algorithm Using Reference-Point-Based Nondominated Sorting Approach,
    Part I: Solving Problems With Box Constraints. IEEE Transactions on
    Evolutionary Computation, 18(4), 577–601. doi:10.1109/TEVC.2013.2281535.
    '''
    assert len(individuals) >= k

    if len(individuals)==k:
        return individuals

    # Algorithm 1 steps 4--8
    fronts = tools.sortLogNondominated(individuals, len(individuals))

    limit = 0
    res =[]
    for f, front in enumerate(fronts):
        res += front
        if len(res) > k:
            limit = f
            break
    # Algorithm 1 steps
    selection = []
    if limit > 0:
        for f in range(limit):
            selection += fronts[f]

    # complete selected inividuals using the referece point based approach
    selection += niching_select(fronts[limit], k - len(selection))
    return selection
Exemplo n.º 2
0
def sel_nsga_iii(individuals, k):
    '''Implements NSGA-III selection as described in
    Deb, K., & Jain, H. (2014). An Evolutionary Many-Objective Optimization
    Algorithm Using Reference-Point-Based Nondominated Sorting Approach,
    Part I: Solving Problems With Box Constraints. IEEE Transactions on
    Evolutionary Computation, 18(4), 577–601. doi:10.1109/TEVC.2013.2281535.
    '''
    assert len(individuals) >= k

    if len(individuals)==k:
        return individuals

    # Algorithm 1 steps 4--8
    fronts = tools.sortLogNondominated(individuals, len(individuals))

    limit = 0
    res =[]
    for f, front in enumerate(fronts):
        res += front
        if len(res) > k:
            limit = f
            break
    # Algorithm 1 steps
    selection = []
    if limit > 0:
        for f in range(limit):
            selection += fronts[f]

    # complete selected inividuals using the referece point based approach
    selection += niching_select(fronts[limit], k - len(selection))
    return selection
Exemplo n.º 3
0
    def generate(self, ind_init):
        """Generate a population of :math:`\lambda` individuals of type
        *ind_init* from the current strategy.

        :param ind_init: A function object that is able to initialize an
                         individual from a list.
        :returns: A list of individuals with a private attribute :attr:`_ps`.
                  This last attribute is essential to the update function, it
                  indicates that the individual is an offspring and the index
                  of its parent.
        """
        arz = numpy.random.randn(self.lambda_, self.dim)
        individuals = list()

        # Make sure every parent has a parent tag and index
        for i, p in enumerate(self.parents):
            p._ps = "p", i

        # Each parent produce an offspring
        if self.lambda_ == self.mu:
            for i in range(self.lambda_):
                # print "Z", list(arz[i])
                individuals.append(ind_init(self.parents[i] + self.sigmas[i] * numpy.dot(self.A[i], arz[i])))
                individuals[-1]._ps = "o", i

        # Parents producing an offspring are chosen at random from the first front
        else:
            ndom = tools.sortLogNondominated(self.parents, len(self.parents), first_front_only=True)
            for i in range(self.lambda_):
                j = numpy.random.randint(0, len(ndom))
                _, p_idx = ndom[j]._ps
                individuals.append(ind_init(self.parents[p_idx] + self.sigmas[p_idx] * numpy.dot(self.A[p_idx], arz[i])))
                individuals[-1]._ps = "o", p_idx

        return individuals
Exemplo n.º 4
0
def nsgaii(model, mu, ngen, cxpb, mutpb):
    assert mu % 4 == 0, "Error: mu is not divisible by 4"

    logging.debug("Working on model " + model.name + " @ NSGAII.py::nsgaii")
    toolbox = base.Toolbox()
    toolbox.register('mate', tools.cxOnePoint)
    toolbox.register('mutate',
                     tools.mutPolynomialBounded,
                     low=0,
                     up=1.0,
                     eta=20.0,
                     indpb=1.0 / model.decNum)
    toolbox.register('select', tools.selNSGA2)

    pop_df = model.init_random_pop(mu)
    model.eval_pd_df(pop_df, normalized=True)

    pop = model.pd_to_deap(pop_df)
    pop = toolbox.select(pop, len(pop))

    for gen in range(1, ngen):
        # _show_pop(sorted(pop, key=lambda i: i[0]))
        logging.debug("Running at gen " + str(gen))
        offspring = tools.selTournamentDCD(pop, len(pop))
        offspring = [toolbox.clone(ind) for ind in offspring]

        t_offspring = list()

        for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
            if random.random() <= cxpb:
                toolbox.mate(ind1, ind2)
                del ind1.fitness.values
                del ind2.fitness.values

            if random.random() <= mutpb:
                toolbox.mutate(ind1)
                toolbox.mutate(ind2)
                del ind1.fitness.values
                del ind2.fitness.values

        # saving new configurations
        if not ind1.fitness.valid:
            t_offspring.append(ind1)
        if not ind1.fitness.valid:
            t_offspring.append(ind2)

        # eval
        offspring_df = model.deap_to_pd(t_offspring)
        model.eval_pd_df(offspring_df, normalized=True)
        offspring = model.pd_to_deap(offspring_df)

        pop = toolbox.select(pop + offspring, mu)

    toolbox.unregister('mate')
    toolbox.unregister('mutate')
    toolbox.unregister('select')

    res = sortLogNondominated(pop, k=10,
                              first_front_only=True)  # k value is non-sense
    return model.deap_to_pd(res)
Exemplo n.º 5
0
def associate(individuals, reference_points):
    '''Associates individuals to reference points and calculates niche number.
    Corresponds to Algorithm 3 of Deb & Jain (2014).'''
    pareto_fronts = tools.sortLogNondominated(individuals, len(individuals))
    num_objs = len(individuals[0].fitness.values)

    for ind in individuals:
        rp_dists = [(rp, perpendicular_distance(ind.fitness.normalized_values, rp))
                    for rp in reference_points]
        best_rp, best_dist = sorted(rp_dists, key=lambda rpd:rpd[1])[0]
        ind.reference_point = best_rp
        ind.ref_point_distance = best_dist
        best_rp.associations_count +=1 # update de niche number
        best_rp.associations += [ind]
Exemplo n.º 6
0
def associate(individuals, reference_points):
    '''Associates individuals to reference points and calculates niche number.
    Corresponds to Algorithm 3 of Deb & Jain (2014).'''
    pareto_fronts = tools.sortLogNondominated(individuals, len(individuals))
    num_objs = len(individuals[0].fitness.values)

    for ind in individuals:
        rp_dists = [(rp, perpendicular_distance(ind.fitness.normalized_values, rp))
                    for rp in reference_points]
        best_rp, best_dist = sorted(rp_dists, key=lambda rpd:rpd[1])[0]
        ind.reference_point = best_rp
        ind.ref_point_distance = best_dist
        best_rp.associations_count +=1 # update de niche number
        best_rp.associations += [ind]
Exemplo n.º 7
0
def plot_pareto_fronts(pop, axes, nfronts=5, showall=True):
    colors = seaborn.color_palette('Set1', n_colors=nfronts)
    fronts = tools.sortLogNondominated(pop, k=len(pop))

    fitnesses = np.array([ind.fitness.values for ind in pop])
    axes.scatter(fitnesses[:, 0],
                 fitnesses[:, 1],
                 color='black',
                 sizes=[2],
                 alpha=.5)

    for i, (color, front) in reversed(list(enumerate(zip(colors, fronts)))):
        fitnesses = np.array([ind.fitness.values for ind in front])
        #axes.scatter(fitnesses[:,0], fitnesses[:,1], color=color, sizes=[6], label=f'Frente {i+1}')
        axes.plot(fitnesses[:, 0],
                  fitnesses[:, 1],
                  marker='o',
                  ms=2,
                  color=color,
                  label=f'Frente {i+1}')
Exemplo n.º 8
0
    def _select(self, candidates):
        if len(candidates) <= self.mu:
            return candidates, []

        pareto_fronts = tools.sortLogNondominated(candidates, len(candidates))

        chosen = list()
        mid_front = None
        not_chosen = list()

        # Fill the next population (chosen) with the fronts until there is not enouch space
        # When an entire front does not fit in the space left we rely on the hypervolume
        # for this front
        # The remaining fronts are explicitely not chosen
        full = False
        for front in pareto_fronts:
            if len(chosen) + len(front) <= self.mu and not full:
                chosen += front
            elif mid_front is None and len(chosen) < self.mu:
                mid_front = front
                # With this front, we selected enough individuals
                full = True
            else:
                not_chosen += front

        # Separate the mid front to accept only k individuals
        k = self.mu - len(chosen)
        if k > 0:
            # reference point is chosen in the complete population
            # as the worst in each dimension +1
            ref = np.array([ind.fitness.wvalues for ind in candidates]) * -1
            ref = np.max(ref, axis=0) + 1

            for _ in range(len(mid_front) - k):
                idx = self.indicator(mid_front, ref=ref)
                not_chosen.append(mid_front.pop(idx))

            chosen += mid_front

        return chosen, not_chosen
def nsga_evolutionary_run(**kwargs):
    """ Conduct an evolutionary run using the snake and muscle model.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """

    # Establish name of the output files and write appropriate headers.
    out_fit_file = args.output_path + str(args.run_num) + "_fitnesses.dat"
    out_fronts_file = args.output_path + str(args.run_num) + "_fronts.dat"
    writeHeaders(out_fit_file)

    creator.create(
        "FitnessMulti", base.Fitness, weights=(1.0, -1.0, 1.0, 1.0)
    )  # Maximize distance, minimize touches, maximize time upright, maximize efficiency
    creator.create("Individual",
                   kwargs['exp_class'],
                   fitness=creator.FitnessMulti)

    # Create the toolbox for setting up DEAP functionality.
    toolbox = base.Toolbox()

    # Define an individual for use in constructing the population.
    toolbox.register("individual", hopper_utils.initIndividual,
                     creator.Individual)
    toolbox.register("mutate", hopper_utils.mutate)
    toolbox.register("crossover", hopper_utils.crossover)

    # Create a population as a list.
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)

    # Register the evaluation function.
    toolbox.register("evaluate", evaluate_individual)

    # Register the selection function.
    toolbox.register("select", tools.selNSGA2)

    # Multiprocessing component.
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores - 2)
    toolbox.register("map", pool.map)

    # Setup the population.
    pop = toolbox.population(n=kwargs['pop_size'])

    # Run the first generation to establish what the initial population does.
    # Evaluate the individuals with an invalid fitness
    invalid_ind = [ind for ind in pop if not ind.fitness.valid]
    fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
    for ind, fit in zip(invalid_ind, fitnesses):
        ind.fitness.values = fit

    # Check to see if a timeout error occurred, if so kill and restart children.
    # timeout = False
    # for f in fitnesses:
    #     if f[0] == -1 and f[1] == 20000:
    #         timeout = True
    # if timeout:
    #     print(mpc.active_children())
    #     pool.terminate()
    #     print(mpc.active_children())
    #     pool = mpc.Pool(processes=cores-2)
    #     toolbox.register("map", pool.map)

    # This is just to assign the crowding distance to the individuals
    # no actual selection is done
    pop = toolbox.select(pop, len(pop))

    # Log the progress of the population. (For Generation 0)
    writeGeneration(out_fit_file, 0, pop)

    # Track the progress of NSGA
    fronts = []
    #fronts.append(','.join(str(i) for i in ind.fitness.values) for ind in pop)
    fronts.append(
        str(ind.id) + ',' + ','.join(str(i) for i in ind.fitness.values)
        for ind in tools.sortLogNondominated(
            pop, args.pop_size, first_front_only=True))

    # Request new id's for the population.
    for ind in pop:
        ind.get_new_id()

    for gen in range(1, args.gens):
        # Variate the population
        offspring = tools.selTournamentDCD(pop, len(pop))
        offspring = [toolbox.clone(ind) for ind in offspring]

        # Update the fronts information.
        #fronts.append(','.join(str(i) for i in ind.fitness.values) for ind in pop)
        fronts.append(
            str(ind.id) + ',' + ','.join(str(i) for i in ind.fitness.values)
            for ind in tools.sortLogNondominated(
                pop, args.pop_size, first_front_only=True))

        # Mutate the population.
        for ind in offspring:
            hopper_utils.mutate(ind)
            del ind.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # Select the next generation population
        pop = toolbox.select(pop + offspring, kwargs['pop_size'])

        # Request new id's for the population.
        for ind in pop:
            ind.get_new_id()

        print("Generation " + str(gen))
        # Log the progress of the population.
        writeGeneration(out_fit_file, gen, pop)

    # Write out the fronts data.
    writeFronts(out_fronts_file, fronts)
Exemplo n.º 10
0
from nsga2 import *
from deap import tools

ind1 = toolbox.individual()
ind2 = toolbox.individual()

ind1.fitness.values = toolbox.evaluate(ind1)
ind2.fitness.values = toolbox.evaluate(ind2)

import pdb

pdb.set_trace()
print(tools.sortLogNondominated([ind1, ind2], k=2))
def nsga_evolution_run(**kwargs):
    """ Base function for the main file to call.  

    Sets up the evolutionary environment and then passes off to the type of 
    evolutionary run that we want to conduct.
    
    Arguments:
        evol_type: type of evolutionary run ['norm_ga','lexicase']
        output_path: where to write the files to
        run_num: run number of the replicate
        pop_size: population size
    """
    # Seed only the evolutionary runs.
    random.seed(args.run_num)

    # Establish name of the output files and write appropriate headers.
    out_fit_file = kwargs['output_path'] + str(
        kwargs['run_num']) + "_fitnesses.dat"
    out_fronts_file = kwargs['output_path'] + str(
        kwargs['run_num']) + "_fronts.dat"
    writeHeaders(out_fit_file, kwargs['exp_class'])

    #creator.create("Fitness", base.Fitness, weights=(1.0,-1.0,1.0,1.0,-1.0,))
    creator.create("Fitness", base.Fitness, weights=(
        1.0,
        1.0,
        -1.0,
    ))

    creator.create("Individual", kwargs['exp_class'], fitness=creator.Fitness)

    # Create the toolbox for setting up DEAP functionality.
    toolbox = base.Toolbox()

    # Define an individual for use in constructing the population.
    toolbox.register("individual", flex_quadruped_utils.initIndividual,
                     creator.Individual)
    toolbox.register("mutate", flex_quadruped_utils.mutate)
    toolbox.register("mate", tools.cxTwoPoint)

    # Create a population as a list.
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)

    # Register the evaluation function.
    toolbox.register("evaluate", evaluate_individual)

    toolbox.register("select", tools.selNSGA2)

    # Multiprocessing component.
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores - 2)
    toolbox.register("map", pool.map)

    # Crossover and mutation probability
    cxpb, mutpb = 0.5, 0.04

    # Set the mutation value for quadruped utils
    flex_quadruped_utils.mutate_chance = mutpb

    # Setup the population.
    pop = toolbox.population(n=kwargs['pop_size'])

    # Run the first set of evaluations.
    invalid_ind = [ind for ind in pop if not ind.fitness.valid]
    fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
    for ind, fit in zip(invalid_ind, fitnesses):
        ind.fitness.values = fit

    # This is just to assign the crowding distance to the individuals
    # no actual selection is done
    pop = toolbox.select(pop, len(pop))

    # Log the progress of the population. (For Generation 0)
    writeGeneration(out_fit_file, 0, pop)

    # Track the progress of NSGA
    fronts = []
    #fronts.append(','.join(str(i) for i in ind.fitness.values) for ind in pop)
    fronts.append(
        str(ind.id) + ',' + ','.join(str(i) for i in ind.fitness.values)
        for ind in tools.sortLogNondominated(
            pop, args.pop_size, first_front_only=True))

    # Request new id's for the population.
    for ind in pop:
        ind.get_new_id()

    for g in range(1, args.gens):
        # Variate the population
        offspring = tools.selTournamentDCD(pop, len(pop))
        offspring = [toolbox.clone(ind) for ind in offspring]

        # Update the fronts information.
        #fronts.append(','.join(str(i) for i in ind.fitness.values) for ind in pop)
        fronts.append(
            str(ind.id) + ',' + ','.join(str(i) for i in ind.fitness.values)
            for ind in tools.sortLogNondominated(
                pop, args.pop_size, first_front_only=True))

        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < cxpb:
                # Must serialize and deserialize due to the type of object.
                child1_serialized, child2_serialized = toolbox.mate(
                    child1.serialize(), child2.serialize())
                child1.deserialize(child1_serialized)
                child2.deserialize(child2_serialized)
                del child1.fitness.values, child2.fitness.values

        # Mutate the population.
        for mutant in offspring:
            toolbox.mutate(mutant)
            del mutant.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # Select the next generation population
        pop = toolbox.select(pop + offspring, kwargs['pop_size'])

        # Request new id's for the population.
        for ind in pop:
            ind.get_new_id()

        print("Generation " + str(g))
        # Log the progress of the population.
        writeGeneration(out_fit_file, g, pop)

    # Write out the fronts data.
    writeFronts(out_fronts_file, fronts)