Example #1
0
def MOTrEO_Ms(function1, function2, max_gen, pop_size, dim, pf_target, source_data=None, source_model_list=None,
               tr_int=None, reg=None, verbose=False):

    """
    By default, this algorithm encodes each variable in the range [0,1]. Decoding step is thus needed during evaluations.

    ## Description of input arguments ##
    function1: first objective function name/handle passed for solution evaluation
    function2: second objective function name/handle passed for solution evaluation
    max_gen: maximum number of generations of EA
    pop_size: population size of EA
    dim: search space dimensionality
    pf_target: target Pareto front
    source_data: solutions of previously encountered (optimized) source problem
    source_model_list: list storing available source model(s)
    tr_int: predefined transfer interval
    reg: regularization coefficient of neural network parameters when learning source-to-target mapping Ms
    """

    if tr_int is None:
        tr_int = 2
    sm_list = copy.deepcopy(source_model_list)
    if pop_size <= 50:
        target_popsize_smaller = True
    else:
        target_popsize_smaller = False

    gen_no = 0
    igd_values = []
    transfer_coefficients = []
    source_data_size = len(source_data[0])

    n_obj = 2
    pf_ref = copy.deepcopy(pf_target)
    pf_ref_len = len(pf_ref)
    max_obj = [0] * n_obj
    min_obj = [0] * n_obj
    for i in range(n_obj):
        pf_ref = sorted(pf_ref, key=lambda obj: obj[i])
        max_obj[i] = pf_ref[pf_ref_len - 1][i]
        min_obj[i] = pf_ref[0][i]
    for i in range(pf_ref_len):
        for j in range(n_obj):
            pf_ref[i][j] = (pf_ref[i][j] - min_obj[j]) / (max_obj[j] - min_obj[j])
    pf_ref_f1 = []
    pf_ref_f2 = []
    for i in range(pf_ref_len):
        pf_ref_f1.append(pf_ref[i][0])
        pf_ref_f2.append(pf_ref[i][1])


    # Initialize search population
    solution = [[random.random() for _ in range(dim)] for _ in range(0, pop_size)]
    function1_values = [function1(solution[i]) for i in range(0, pop_size)]
    function2_values = [function2(solution[i]) for i in range(0, pop_size)]

    while (gen_no < max_gen):
        non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:])
        print("MOTrEO+Ms Output for Generation ", gen_no, " :")
        parent_front_f11 = []
        parent_front_f22 = []
        non_dominated_sorted_solution[0].sort()
        for index in non_dominated_sorted_solution[0]:
            parent_front_f11.append(function1_values[index])
            parent_front_f22.append(function2_values[index])

        # Compute IGD values
        parent_front_f1 = []
        parent_front_f2 = []
        for i in range(len(parent_front_f11)):
            parent_front_f1.append((parent_front_f11[i] - min_obj[0]) / (max_obj[0] - min_obj[0]))
            parent_front_f2.append((parent_front_f22[i] - min_obj[1]) / (max_obj[1] - min_obj[1]))
        sum_dist = 0
        for i in range(pf_ref_len):
            min_dist = math.inf
            for j in range(len(parent_front_f1)):
                dist2 = pow(parent_front_f1[j] - pf_ref_f1[i], 2.0) + pow(parent_front_f2[j] - pf_ref_f2[i], 2.0)
                dist = math.sqrt(dist2)
                if dist < min_dist:
                    min_dist = dist
            sum_dist += min_dist
        igd = sum_dist / pf_ref_len
        igd_values.append(igd)
        print('IGD = ', igd)

        # Generate offsprings
        solution2 = solution[:]
        while (len(solution2) < 2 * pop_size):
            if (gen_no + 1) % tr_int == 0:
                # Learn non-linear source-to-target mapping at specified transfer intervals
                if target_popsize_smaller:
                    generational_solutions = np.array(solution)
                    source_data_subpop = []
                    source_data_indices = random.sample(range(0, source_data_size), pop_size)
                    source_data_indices.sort()
                    for i in range(pop_size):
                        source_data_subpop.append(source_data[gen_no][source_data_indices[i]])
                    source_data_subpop = np.array(source_data_subpop)
                    map = learn_map(source_data_subpop, generational_solutions, reg)
                else:
                    target_data_subpop = []
                    target_data_indices = random.sample(range(0, pop_size), source_data_size)
                    target_data_indices.sort()
                    for i in range(source_data_size):
                        target_data_subpop.append(solution[target_data_indices[i]])
                    generational_solutions = np.array(target_data_subpop)
                    map = learn_map(source_data[gen_no], generational_solutions, reg)

                # offspring generated by sampling the target probabilistic mixture model
                new_models = [model_transform(sm_list[0], map)]
                mm = MixtureModel(new_models)
                mm.createTable(np.array(solution), True, 'mvarnorm')
                mm.EMstacking()
                mm.mutate()
                coefficients = np.around(mm.alpha, decimals=5)
                transfer_coefficients.append(coefficients[0])
                if verbose: print("Transfer coefficients = ", coefficients)

                offspring_A = mm.sample(pop_size)
                for i in range(0, len(offspring_A)):
                    offspring_B = check_bounds(offspring_A[i])
                    solution2.append(offspring_B)

            else:
                # Offspring creation via standard reproduction during non-transfer intervals
                a1 = random.randint(0, pop_size - 1)
                a2 = random.randint(0, pop_size - 1)
                a = binary_tournament(a1, a2, function1_values[:], function2_values[:])
                b1 = random.randint(0, pop_size - 1)
                b2 = random.randint(0, pop_size - 1)
                b = binary_tournament(b1, b2, function1_values[:], function2_values[:])
                c1, c2 = SBX_crossover(solution[a], solution[b])
                c1_mutated, c2_mutated = polynomial_mutation(c1, c2)
                solution2.append(c1_mutated)
                solution2.append(c2_mutated)
        function1_values2 = function1_values[:]
        function2_values2 = function2_values[:]
        for i in range(pop_size, 2 * pop_size):
            function1_values2.append(function1(solution2[i]))
            function2_values2.append(function2(solution2[i]))
        non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:])
        crowding_distance_values2 = []
        for i in range(0, len(non_dominated_sorted_solution2)):
            crowding_distance_values2.append(crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:]))

        # Environmental selection
        new_solution = []
        function1_values = []
        function2_values = []
        for i in range(0, len(non_dominated_sorted_solution2)):
            non_dominated_sorted_solution2[i].sort()
            front = sort_distance(non_dominated_sorted_solution2[i], crowding_distance_values2[i])
            front.reverse()
            for index in front:
                new_solution.append(solution2[index])
                function1_values.append(function1_values2[index])
                function2_values.append(function2_values2[index])
                if (len(new_solution) == pop_size):
                    break
            if (len(new_solution) == pop_size):
                break

        solution = new_solution[:]
        gen_no = gen_no + 1
        print("\n")


    return igd_values, transfer_coefficients
Example #2
0
def MOTrEO_RSM(function1, function2, max_gen, pop_size, dim, pf_target, tr_int=None,
                transfer_coefficients=None):
    """
    By default, this algorithm encodes each variable in the range [0,1]. Decoding step is thus needed during evaluations.

    ## Description of input arguments ##
    function1: first objective function name/handle passed for solution evaluation
    function2: second objective function name/handle passed for solution evaluation
    max_gen: maximum number of generations of EA
    pop_size: population size of EA
    dim: search space dimensionality
    pf_target: target Pareto front
    tr_int: predefined transfer interval
    transfer_coefficients: coefficients obtained in the MOTrEO+Ms, used to determine the extent of knowledge transfers in the MOTrEO(RSM)
    """

    if tr_int is None:
        tr_int = 2

    gen_no = 0
    igd_values = []
    transfer_counter = 0

    n_obj = 2
    pf_ref = copy.deepcopy(pf_target)
    pf_ref_len = len(pf_ref)
    max_obj = [0] * n_obj
    min_obj = [0] * n_obj
    for i in range(n_obj):
        pf_ref = sorted(pf_ref, key=lambda obj: obj[i])
        max_obj[i] = pf_ref[pf_ref_len - 1][i]
        min_obj[i] = pf_ref[0][i]
    for i in range(pf_ref_len):
        for j in range(n_obj):
            pf_ref[i][j] = (pf_ref[i][j] - min_obj[j]) / (max_obj[j] - min_obj[j])
    pf_ref_f1 = []
    pf_ref_f2 = []
    for i in range(pf_ref_len):
        pf_ref_f1.append(pf_ref[i][0])
        pf_ref_f2.append(pf_ref[i][1])


    # Initialize search population
    solution = [[random.random() for _ in range(dim)] for _ in range(0, pop_size)]
    function1_values = [function1(solution[i]) for i in range(0, pop_size)]
    function2_values = [function2(solution[i]) for i in range(0, pop_size)]

    while (gen_no < max_gen):
        non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:])
        print("MOTrEO(RSM) Output for Generation ", gen_no, " :")
        parent_front_f11 = []
        parent_front_f22 = []
        non_dominated_sorted_solution[0].sort()
        for index in non_dominated_sorted_solution[0]:
            parent_front_f11.append(function1_values[index])
            parent_front_f22.append(function2_values[index])

        # Compute IGD values
        parent_front_f1 = []
        parent_front_f2 = []
        for i in range(len(parent_front_f11)):
            parent_front_f1.append((parent_front_f11[i] - min_obj[0]) / (max_obj[0] - min_obj[0]))
            parent_front_f2.append((parent_front_f22[i] - min_obj[1]) / (max_obj[1] - min_obj[1]))
        sum_dist = 0
        for i in range(pf_ref_len):
            min_dist = math.inf
            for j in range(len(parent_front_f1)):
                dist2 = pow(parent_front_f1[j] - pf_ref_f1[i], 2.0) + pow(parent_front_f2[j] - pf_ref_f2[i], 2.0)
                dist = math.sqrt(dist2)
                if dist < min_dist:
                    min_dist = dist
            sum_dist += min_dist
        igd = sum_dist / pf_ref_len
        igd_values.append(igd)
        print('IGD = ', igd)

        # Generating offsprings
        solution2 = solution[:]
        while (len(solution2) < 2 * pop_size):
            a1 = random.randint(0, pop_size - 1)
            a2 = random.randint(0, pop_size - 1)
            a = binary_tournament(a1, a2, function1_values[:], function2_values[:])
            b1 = random.randint(0, pop_size - 1)
            b2 = random.randint(0, pop_size - 1)
            b = binary_tournament(b1, b2, function1_values[:], function2_values[:])
            c1, c2 = SBX_crossover(solution[a], solution[b])
            c1_mutated, c2_mutated = polynomial_mutation(c1, c2)
            solution2.append(c1_mutated)
            solution2.append(c2_mutated)

        function1_values2 = function1_values[:]
        function2_values2 = function2_values[:]
        for i in range(pop_size, 2 * pop_size):
            function1_values2.append(function1(solution2[i]))
            function2_values2.append(function2(solution2[i]))

        # Knowledge transfers from a RSM based on the transfer coefficients obtained in the MOTrEO+Ms
        if (gen_no + 1) % tr_int == 0:
            offspring_sample_size = np.ceil(pop_size * transfer_coefficients[transfer_counter]).astype(int)
            if offspring_sample_size >= 1:
                indx = random.sample(range(0, 2 * pop_size), offspring_sample_size)
                for i in range(offspring_sample_size):
                    transferred_sol = [random.uniform(0, 1) for _ in range(dim)]
                    solution2[indx[i]] = transferred_sol
                    function1_values2[indx[i]] = function1(transferred_sol)
                    function2_values2[indx[i]] = function2(transferred_sol)
            transfer_counter += 1

        non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:])
        crowding_distance_values2 = []
        for i in range(0, len(non_dominated_sorted_solution2)):
            crowding_distance_values2.append(crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:]))

        # Environmental selection
        new_solution = []
        function1_values = []
        function2_values = []
        for i in range(0, len(non_dominated_sorted_solution2)):
            non_dominated_sorted_solution2[i].sort()
            front = sort_distance(non_dominated_sorted_solution2[i], crowding_distance_values2[i])
            front.reverse()
            for index in front:
                new_solution.append(solution2[index])
                function1_values.append(function1_values2[index])
                function2_values.append(function2_values2[index])
                if (len(new_solution) == pop_size):
                    break
            if (len(new_solution) == pop_size):
                break

        solution = new_solution[:]
        gen_no = gen_no + 1
        print("\n")


    return igd_values
Example #3
0
def NSGA2(function1, function2, max_gen, pop_size, dim, pf_target):

    """
    By default, this algorithm encodes each variable in the range [0,1]. Decoding step is thus needed during evaluations.

    ## Description of input arguments ##
    function1: first objective function name/handle passed for solution evaluation
    function2: second objective function name/handle passed for solution evaluation
    max_gen: maximum number of generations of EA
    pop_size: population size of EA
    dim: search space dimensionality
    pf_target: approximated target Pareto front
    """

    gen_no = 0
    igd_values = []

    n_obj = 2
    pf_ref = copy.deepcopy(pf_target)
    pf_ref_len = len(pf_ref)
    max_obj = [0] * n_obj
    min_obj = [0] * n_obj
    for i in range(n_obj):
        pf_ref = sorted(pf_ref, key=lambda obj: obj[i])
        max_obj[i] = pf_ref[pf_ref_len - 1][i]
        min_obj[i] = pf_ref[0][i]
    for i in range(pf_ref_len):
        for j in range(n_obj):
            pf_ref[i][j] = (pf_ref[i][j] - min_obj[j]) / (max_obj[j] - min_obj[j])
    pf_ref_f1 = []
    pf_ref_f2 = []
    for i in range(pf_ref_len):
        pf_ref_f1.append(pf_ref[i][0])
        pf_ref_f2.append(pf_ref[i][1])

    # Initialize search population
    solution = [[random.random() for _ in range(dim)] for _ in range(0, pop_size)]
    function1_values = [function1(solution[i]) for i in range(0, pop_size)]
    function2_values = [function2(solution[i]) for i in range(0, pop_size)]

    while (gen_no < max_gen):
        non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:])
        print("NSGA-II Output for Generation ", gen_no, " :")
        parent_front_f11 = []
        parent_front_f22 = []
        non_dominated_sorted_solution[0].sort()
        for index in non_dominated_sorted_solution[0]:
            parent_front_f11.append(function1_values[index])
            parent_front_f22.append(function2_values[index])

        # Compute IGD values
        parent_front_f1 = []
        parent_front_f2 = []
        for i in range(len(parent_front_f11)):
            parent_front_f1.append((parent_front_f11[i] - min_obj[0]) / (max_obj[0] - min_obj[0]))
            parent_front_f2.append((parent_front_f22[i] - min_obj[1]) / (max_obj[1] - min_obj[1]))
        sum_dist = 0
        for i in range(pf_ref_len):
            min_dist = math.inf
            for j in range(len(parent_front_f1)):
                dist2 = pow(parent_front_f1[j] - pf_ref_f1[i], 2.0) + pow(parent_front_f2[j] - pf_ref_f2[i], 2.0)
                dist = math.sqrt(dist2)
                if dist < min_dist:
                    min_dist = dist
            sum_dist += min_dist
        igd = sum_dist / pf_ref_len
        igd_values.append(igd)
        print('IGD = ', igd)

        # Generating offsprings
        solution2 = solution[:]
        while (len(solution2) < 2 * pop_size):
            a1 = random.randint(0, pop_size - 1)
            a2 = random.randint(0, pop_size - 1)
            a = binary_tournament(a1, a2, function1_values[:], function2_values[:])
            b1 = random.randint(0, pop_size - 1)
            b2 = random.randint(0, pop_size - 1)
            b = binary_tournament(b1, b2, function1_values[:], function2_values[:])
            c1, c2 = SBX_crossover(solution[a], solution[b])
            c1_mutated, c2_mutated = polynomial_mutation(c1, c2)
            solution2.append(c1_mutated)
            solution2.append(c2_mutated)
        function1_values2 = function1_values[:]
        function2_values2 = function2_values[:]
        for i in range(pop_size, 2 * pop_size):
            function1_values2.append(function1(solution2[i]))
            function2_values2.append(function2(solution2[i]))
        non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:])
        crowding_distance_values2 = []
        for i in range(0, len(non_dominated_sorted_solution2)):
            crowding_distance_values2.append(crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:]))

        # Environmental selection
        new_solution = []
        function1_values = []
        function2_values =[]
        for i in range(0, len(non_dominated_sorted_solution2)):
            non_dominated_sorted_solution2[i].sort()
            front = sort_distance(non_dominated_sorted_solution2[i], crowding_distance_values2[i])
            front.reverse()
            for index in front:
                new_solution.append(solution2[index])
                function1_values.append(function1_values2[index])
                function2_values.append(function2_values2[index])
                if (len(new_solution) == pop_size):
                    break
            if (len(new_solution) == pop_size):
                break

        solution = new_solution[:]
        gen_no = gen_no + 1
        print("\n")

    return igd_values