经典多目标优化算法Python实现

International Journal of Complexity in Applied Science and Technology,收录进化计算,机器学习和大数据方面的论文, 网址:https://www.inderscience.com/jhome.php?jcode=ijcast 

########python Copy code########
# 导入所需模块
import math
import random
import matplotlib.pyplot as plt

# 第一个要优化的函数
def function1(x):
    value = -x**2
    return value

# 第二个要优化的函数
def function2(x):
    value = -(x-2)**2
    return value

# 查找列表中元素的索引
def index_of(a, list):
    for i in range(0, len(list)):
        if list[i] == a:
            return i
    return -1

# 根据值对列表进行排序
def sort_by_values(list1, values):
    sorted_list = []
    while len(sorted_list) != len(list1):
        if index_of(min(values), values) in list1:
            sorted_list.append(index_of(min(values), values))
        values[index_of(min(values), values)] = math.inf
    return sorted_list

# 实现NSGA-II的快速非支配排序
def fast_non_dominated_sort(values1, values2):
    S = [[] for i in range(0, len(values1))]
    front = [[]]
    n = [0 for i in range(0, len(values1))]
    rank = [0 for i in range(0, len(values1))]

    for p in range(0, len(values1)):
        S[p] = []
        n[p] = 0
        for q in range(0, len(values1)):
            if (values1[p] > values1[q] and values2[p] > values2[q]) or \
               (values1[p] >= values1[q] and values2[p] > values2[q]) or \
               (values1[p] > values1[q] and values2[p] >= values2[q]):
                if q not in S[p]:
                    S[p].append(q)
            elif (values1[q] > values1[p] and values2[q] > values2[p]) or \
                 (values1[q] >= values1[p] and values2[q] > values2[p]) or \
                 (values1[q] > values1[p] and values2[q] >= values2[p]):
                n[p] = n[p] + 1
        if n[p] == 0:
            rank[p] = 0
            if p not in front[0]:
                front[0].append(p)

    i = 0
    while front[i] != []:
        Q = []
        for p in front[i]:
            for q in S[p]:
                n[q] = n[q] - 1
                if n[q] == 0:
                    rank[q] = i + 1
                    if q not in Q:
                        Q.append(q)
        i = i + 1
        front.append(Q)

    del front[len(front) - 1]
    return front

# 计算拥挤距离
def crowding_distance(values1, values2, front):
    distance = [0 for i in range(0, len(front))]
    sorted1 = sort_by_values(front, values1[:])
    sorted2 = sort_by_values(front, values2[:])
    distance[0] = 4444444444444444
    distance[len(front) - 1] = 4444444444444444
    for k in range(1, len(front) - 1):
        distance[k] = distance[k] + (values1[sorted1[k + 1]] - values2[sorted1[k - 1]]) / (max(values1) - min(values1))
    for k in range(1, len(front) - 1):
        distance[k] = distance[k] + (values1[sorted2[k + 1]] - values2[sorted2[k - 1]]) / (max(values2) - min(values2))
    return distance

# 执行交叉操作
def crossover(a, b):
    r = random.random()
    if r > 0.5:
        return mutation((a + b) / 2)
    else:
        return mutation((a - b) / 2)

# 执行变异操作
def mutation(solution):
    mutation_prob = random.random()
    if mutation_prob < 1:
        solution = min_x + (max_x - min_x) * random.random()
    return solution

# 主程序从这里开始
pop_size = 20  # 种群大小
max_gen = 921  # 最大代数

# 初始化
min_x = -55
max_x = 55
solution = [min_x + (max_x - min_x) * random.random() for i in range(0, pop_size)]
gen_no = 0

while gen_no < max_gen:
    # 计算当前种群中每个个体的目标函数值
    function1_values = [function1(solution[i]) for i in range(0, pop_size)]
    function2_values = [function2(solution[i]) for i in range(0, pop_size)]
    
    # 进行快速非支配排序
    non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:])
    print("The best front for Generation number ", gen_no, " is")
    for valuez in non_dominated_sorted_solution[0]:
        print(round(solution[valuez], 3), end=" ")
    print("\n")
    
    # 计算每个前沿的拥挤距离
    crowding_distance_values = []
    for i in range(0, len(non_dominated_sorted_solution)):
        crowding_distance_values.append(crowding_distance(function1_values[:], function2_values[:], non_dominated_sorted_solution[i][:]))
    
    # 复制当前种群
    solution2 = solution[:]
    
    # 生成子代
    while len(solution2) != 2 * pop_size:
        a1 = random.randint(0, pop_size - 1)
        b1 = random.randint(0, pop_size - 1)
        solution2.append(crossover(solution[a1], solution[b1]))
    
    # 计算子代的目标函数值
    function1_values2 = [function1(solution2[i]) for i in range(0, 2 * pop_size)]
    function2_values2 = [function2(solution2[i]) for i in range(0, 2 * pop_size)]
    
    # 对子代进行快速非支配排序
    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][:]))
    
    new_solution = []
    for i in range(0, len(non_dominated_sorted_solution2)):
        non_dominated_sorted_solution2_1 = [index_of(non_dominated_sorted_solution2[i][j], non_dominated_sorted_solution2[i]) for j in range(0, len(non_dominated_sorted_solution2[i]))]
        front22 = sort_by_values(non_dominated_sorted_solution2_1[:], crowding_distance_values2[i][:])
        front = [non_dominated_sorted_solution2[i][front22[j]] for j in range(0, len(non_dominated_sorted_solution2[i]))]
        front.reverse()
        for value in front:
            new_solution.append(value)
            if len(new_solution) == pop_size:
                break
        if len(new_solution) == pop_size:
            break
    
    # 更新种群
    solution = [solution2[i] for i in new_solution]
    gen_no = gen_no + 1

# 绘制最终前沿
function1 = [i * -1 for i in function1_values]
function2 = [j * -1 for j in function2_values]
plt.xlabel('Function 1', fontsize=15)
plt.ylabel('Function 2', fontsize=15)
plt.scatter(function1, function2)
plt.show()

每一步解释

  1. 导入模块:

    • math: 提供数学函数。
    • random: 用于生成随机数。
    • matplotlib.pyplot: 用于绘制图形。
  2. 定义目标函数:

    • function1(x): 第一个目标函数,返回 -x**2
    • function2(x): 第二个目标函数,返回 -(x-2)**2
  3. 辅助函数:

    • index_of(a, list): 返回列表中元素 a 的索引,如果不存在返回 -1。
    • sort_by_values(list1, values): 根据 valueslist1 进行排序,返回排序后的索引列表。
  4. 快速非支配排序:

    • fast_non_dominated_sort(values1, values2): 实现快速非支配排序,分配等级并返回前沿。
  5. 计算拥挤距离:

    • crowding_distance(values1, values2, front): 计算个体之间的拥挤距离,用于选择多样性。
  6. 交叉与变异:

    • crossover(a, b): 实现交叉操作。
    • mutation(solution): 实现变异操作。
  7. 主程序:

    • 初始化种群大小、最大代数、变量范围。
    • 生成初始种群。
    • 在每一代中:
      • 计算种群中每个个体的目标函数值。
      • 进行快速非支配排序。
      • 计算每个前沿的拥挤距离。
      • 生成子代并计算其目标函数值。
      • 对子代进行快速非支配排序。
      • 更新种群。
  8. 绘制结果:

    • 绘制两个目标函数的Pareto前沿。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值