예제 #1
0
def pool_pareto_distance_tournament(parents, children, pareto_front,
                                    optimization_type):
    """
    This selector chooses two individuals randomly from the combined 
    population of parents and their mutated offspring and compares their
    scores and the fitter individual is selected. In case that both are
    equally fit, the one with the greater distance to . The individuals compete until 
    no individuals are left. 
    """
    p = Population()
    result = Population()
    p.add_population(parents)
    p.add_population(children)

    reference_pop = Population()
    reference_pop.add_population(parents)
    reference_pop.add_population(children)
    reference_pop.add_population(pareto_front)
    #=======================================================================
    # iterate over half of the combined population
    #=======================================================================
    num_elements = len(parents.individuals)
    for i in range(num_elements):
        choose_1 = np.random.randint(0, len(p.individuals))
        c1 = p.individuals.pop(choose_1)
        choose_2 = np.random.randint(0, len(p.individuals))
        c2 = p.individuals.pop(choose_2)
        # find the fitter individual, choose randomly, if none dominates
        # the other
        fitter_individual = who_is_fitter_max_distance_all(
            c1, c2, reference_pop, optimization_type)
        # add the fitter one to the returned population
        result.add(fitter_individual)

    return result
예제 #2
0
def nsga_tournament(parents, children, pareto_front, optimization_type):
    '''
    Replaces population using the non-dominated sorting technique from
    NSGA-II. Fill new parent population according to the best front
    respectively crowding distance within a front 
    '''
    pool = Population()
    pool.add_population(parents)
    pool.add_population(children)
    survivors = Population()

    # give each individual their attributes:
    for indi in pool.individuals:
        indi.crowding_distance = 0
        indi.pareto_rank = -1

    # get a list filled with the pareto fronts
    pareto_shells = pool.get_pareto_shells(optimization_type)

    # calculate the crowding distance for each individual (yes, this can be
    # optimized,but this way it can be used by other methods as well
    # -> copy + paste)
    for pareto_rank, shell in enumerate(pareto_shells):
        for objective, score in enumerate(shell.individuals[0].score):
            # sort by this objective
            shell.individuals.sort(key=lambda x: x.score[objective])
            for indi_index, indi in enumerate(shell.individuals):
                if indi_index == 0:
                    indi.crowding_distance = np.inf
                    indi.pareto_rank = pareto_rank + 1
                elif indi_index == shell.size() - 1:
                    indi.crowding_distance = np.inf
                    indi.pareto_rank = pareto_rank + 1
                else:
                    # individuals are sorted by the current objective and now we
                    # get the min and max value to normalize the fitness
                    diff_min = shell.individuals[0].score[objective]
                    diff_max = shell.individuals[-1].score[objective]
                    diff = diff_max - diff_min
                    if diff == 0:
                        diff = 1
                    distance_l = shell.individuals[indi_index -
                                                   1].score[objective]
                    distance_r = shell.individuals[indi_index +
                                                   1].score[objective]
                    indi.crowding_distance = (indi.crowding_distance +
                                              distance_l + distance_r)

    # fill survivors
    for shell in pareto_shells:
        if len(survivors.individuals) == len(parents.individuals):
            break

        elif len(survivors.individuals) + shell.size() > len(
                parents.individuals):
            # we can not add all elements, so we sort them by their crowding
            # distance and use the best until survivors is full
            shell.individuals.sort(key=lambda x: x.crowding_distance)

            i = 0
            while len(survivors.individuals) < len(parents.individuals):
                survivors.add(shell.individuals[i])
                i += 1

        else:
            for indi in shell.individuals:
                survivors.add(indi)

    return survivors
예제 #3
0
def nsga_random_tournament(parents, children, pareto_front, optimization_type):
    """
    Replaces population using the non-dominated sorting technique from NSGA-II.
    Fill new parent population according to the best front respectively crowding distance within a front 
    """
    pool = Population()
    pool.add_population(parents)
    pool.add_population(children)
    survivors = Population()

    # give each individual their attributes:
    for indi in pool.individuals:
        indi.crowding_distance = 0
        indi.pareto_rank = -1

    # get a list filled with the pareto fronts
    pareto_shells = pool.get_pareto_shells(optimization_type)

    # calculate the crowding distance for each individual (yes, this can be
    # optimized,but this way it can be used by other methods as well
    # -> copy + paste)
    for pareto_rank, shell in enumerate(pareto_shells):
        for objective, score in enumerate(shell[0].score):
            # sort by this objective
            shell.sort(key=lambda x: x.score[objective])
            for indi_index, indi in enumerate(shell):
                if indi_index == 0:
                    indi.crowding_distance = np.inf
                    indi.pareto_rank = pareto_rank + 1
                elif indi_index == len(shell) - 1:
                    indi.crowding_distance = np.inf
                    indi.pareto_rank = pareto_rank + 1
                else:
                    # individuals are sorted by the current objective and now we
                    # get the min and max value to normalize the fitness
                    diff_min = shell[0].score[objective]
                    diff_max = shell[-1].score[objective]
                    diff = diff_max - diff_min
                    if diff == 0:
                        diff = 1
                    distance_l = shell[indi_index - 1].score[objective]
                    distance_r = shell[indi_index + 1].score[objective]
                    indi.crowding_distance = (indi.crowding_distance +
                                              distance_l + distance_r)

    for i in range(len(parents.individuals)):
        choose_1 = np.random.randint(0, len(pool.individuals))
        c1 = pool.individuals.pop(choose_1)
        choose_2 = np.random.randint(0, len(pool.individuals))
        c2 = pool.individuals.pop(choose_2)

        if c1.pareto_rank < c2.pareto_rank:
            # c1 is better
            survivors.add(c1)
        elif c1.pareto_rank > c2.pareto_rank:
            # c2 is better
            survivors.add(c2)
        else:
            # both are in the same shell
            if c1.crowding_distance > c2.crowding_distance:
                # c1 should be prefered because it is lonley, there are
                # no friends nearby
                survivors.add(c1)
            elif c1.crowding_distance < c2.crowding_distance:
                # c2 should be prefered
                survivors.add(c2)
            else:
                # very unlikely, both are equal -> choose random
                if np.random.randint(0, 2) == 1:
                    # c1 won the lottery
                    survivors.add(c1)
                else:
                    # c2 has won
                    survivors.add(c2)

    return survivors