コード例 #1
0
def pareto_energy_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, their energy towards the pareto front will be caluclated and
    the one with the lower energy will be chosen. The individuals compete until 
    no individuals are left. 
    """
    p = Population()
    result = Population()
    p.add_population(parents)
    p.add_population(children)
    #=======================================================================
    # 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_min_energy_all(
            c1, c2, pareto_front, optimization_type)
        # add the fitter one to the returned population
        result.add(fitter_individual)

    return result
コード例 #2
0
def who_is_fitter_min_energy_all(c1, c2, population, optimization_type):
    '''
    This method returns the fitter individual form the two candidates
    c1 and c2. In case none dominates the other, the distance to all other
    individual is calculated and the one with the greater distance is 
    chosen to increase the diversity.
    '''
    #===================================================================
    # For minimization:
    # append 1 if c1.value is smaller than c2's
    # append 2 if c1.value is equal to c2's
    # append 0 if C1.value is bigger than c2's
    # for maximization 1 is switched with 0
    #===================================================================
    p = Population()
    if optimization_type == p.minimize:
        relation_case_0 = 1
        relation_case_1 = 2
        relation_case_2 = 0
    elif optimization_type == p.maximize:
        relation_case_0 = 0
        relation_case_1 = 2
        relation_case_2 = 1
    else:
        raise ValueError(
            "Unkown input for optimization_type: '{0}', should be 'min' or 'max'!"
            .format(optimization_type))
    # list to find the fitter individual
    compare_list = []
    for j in range(len(c1.score)):
        if c1.score[j] < c2.score[j]:
            compare_list.append(relation_case_0)
        elif c1.score[j] == c2.score[j]:
            compare_list.append(relation_case_1)
        elif c1.score[j] > c2.score[j]:
            compare_list.append(relation_case_2)

    #===================================================================
    # check the relation of the individuals
    #===================================================================
    if 0 not in compare_list and 1 in compare_list:
        # c1 is smaller than c2
        return c1
    elif 1 not in compare_list and 0 in compare_list:
        # c1 is bigger than c2
        return c2
    else:

        energy_c1 = c1.score_energy_with_population(population, c2.unique_id)
        energy_c2 = c2.score_energy_with_population(population, c1.unique_id)
        if energy_c1 < energy_c2:
            return c1
        elif energy_c1 > energy_c2:
            return c2
        # very unlikely but you never know
        else:
            if np.random.randint(0, 2) == 1:
                return c1
            else:
                return c2
コード例 #3
0
def who_is_fitter_random(c1, c2, optimization_type):
    '''
        This method returns the fitter individual form the two candidates
        c1 and c2. In case none dominates the other, one is randomly chosen.
        '''
    #===================================================================
    # For minimization:
    # append 1 if c1.value is smaller than c2's
    # append 2 if c1.value is equal to c2's
    # append 0 if C1.value is bigger than c2's
    # for maximization 1 is switched with 0
    #===================================================================
    p = Population()
    if optimization_type == p.minimize:
        relation_case_0 = 1
        relation_case_1 = 2
        relation_case_2 = 0
    elif optimization_type == p.maximize:
        relation_case_0 = 0
        relation_case_1 = 2
        relation_case_2 = 1
    else:
        raise ValueError(
            "Unkown input for optimization_type: '{0}', should be 'min' or 'max'!"
            .format(optimization_type))
    # list to find the fitter individual
    compare_list = []
    for j in range(len(c1.score)):
        if c1.score[j] < c2.score[j]:
            compare_list.append(relation_case_0)
        elif c1.score[j] == c2.score[j]:
            compare_list.append(relation_case_1)
        elif c1.score[j] > c2.score[j]:
            compare_list.append(relation_case_2)

    #===================================================================
    # check the relation of the individuals
    #===================================================================
    if 0 not in compare_list and 1 in compare_list:
        # c1 is smaller than c2
        return c1
    elif 1 not in compare_list and 0 in compare_list:
        # c1 is bigger than c2
        return c2
    else:
        if np.random.randint(0, 2) == 1:
            return c1
        else:
            return c2
コード例 #4
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
コード例 #5
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