问题描述如下:
解决方案:
参数初始化:
import heapq
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from scipy.optimize import minimize,fsolve,Bounds
#所有设施
F1 = [8,16];F2 = [8,16];F3 = [8,14];F4 = [8,12];F5 = [8,10];F6 = [8,8];
F7 = [8,8];F8 = [6,6];F9 = [6,6];F10 = [4,6];F11 = [4,4];F12 = [10,10];
F13 = [0,0] #点坐标
F14 = [0,0] #点坐标
F15 = [20,32]
F16 = [24,68]
F17 = [8,8]
F18 = [50,8]
F19 = [10,34]
F = [F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16,F17,F18,F19]
#物流量f
f = np.zeros((14,14))
f[0,1] = 1800;f[0,9] = 2;f[0,11] = 32;f[0,12] = 740;f[0,13] = 492;f[1,11] = 4;
f[1,12] = 275;f[1,13] = 198;f[2,3] = 1085;f[2,11] = 168;f[2,12] = 321;
f[2,13] = 103;f[3,11] = 12;f[3,12] = 438;f[3,13] = 210;f[4,11] = 87;
f[4,12] = 320;f[4,13] = 105;f[5,7] = 620;f[5,8] = 80;f[5,11] = 2;f[5,12] = 550;
f[5,13] = 323;f[6,11] = 6;f[6,12] = 1132;f[6,13] = 722
f += f.T - np.diag(f.diagonal())
#关系值
#物流量f
s = np.zeros((14,14))
s[0,1] = 81;s[0,3] = -9;s[0,4] = -27;s[0,5] = -27;s[0,9] = 9;s[0,10] = 27;s[0,11] = -9;
s[0,12] = 27;s[0,13] = 81;s[1,5] = -9;s[1,8] = 9;s[1,12] = 9;s[1,13] = 9;s[2,3] = 81;
s[2,4] = 27;s[2,5] = -9;s[2,11] = 9;s[2,12] = 9;s[2,13] = 9;s[3,4] = -27;s[3,5] = -27;
s[3,6] = -9;s[3,7] = -9;s[3,8] = -9;s[3,9] = -9;s[3,10] = 27;s[3,11] = 9;s[3,12] = 27;
s[3,13] = 27;s[4,8] = 9;s[4,12] = 27;s[4,13] = 27;s[5,6] = 9;s[5,7] = 81;s[5,8] = 27;
s[5,9] = 9;s[5,10] = 9;s[5,12] = 81;s[5,13] = 81;s[6,7] = 27;s[6,8] = 9;s[6,12] = 27;
s[6,13] = 27;s[8,10] = 27;s[8,11] = 9;s[9,10] = 27
s += s.T - np.diag(s.diagonal())
约束条件:
from parameters import *
#所有的约束条件
#约束条件1,实际上没有考虑左下角和右下角缺损的情况,这个会在Cons2里面设计
def Cons1():
return bounds
#约束条件2和3放在一起了
def Cons2(x):
return ress1+ress2+ress3+ress4
目标函数:
from parameters import *
import constraints as cs
#目标函数1
def Obj_F1(xy):
res = 0
d = np.zeros((14,14))
for i in range(12):
for j in range(12):
d[i,j] = abs(xy[i*2] - xy[j*2]) + abs(xy[i*2+1] - xy[j*2+1])
for i in range(12):
d[i][12] = abs(xy[i*2] - 24) + abs(xy[i*2+1] - 40)
d[i][13] = abs(xy[i*2] - 62) + abs(xy[i*2+1] - 80)
for i in range(12):
d[12][i] = d[i][12]
d[13][i] = d[i][13]
for i in range(14):
for j in range(i+1, 14):
res += f[i][j] * d[i][j]
#因为是目标函数1的希望取最小值,而遗传算法是求适应度的最大值,所以设计如下,
#乘以20000是作为罚函数的增益,保证约束条件设计值和目标函数值在差不多大小
#既返回适应度值给遗传算法,也将约束条件设计值进行返回,便于后期画目标函数收敛曲线图
return cs.Cons2(xy)*20000-res,cs.Cons2(xy)*20000
#目标函数2
def Obj_F2(xy):
res = 0
d = np.zeros((14,14))
for i in range(12):
for j in range(12):
d[i,j] = abs(xy[i*2] - xy[j*2]) + abs(xy[i*2+1] - xy[j*2+1])
for i in range(12):
d[i][12] = abs(xy[i*2] - 24) + abs(xy[i*2+1] - 40)
d[i][13] = abs(xy[i*2] - 62) + abs(xy[i*2+1] - 80)
for i in range(12):
d[12][i] = d[i][12]
d[13][i] = d[i][13]
for i in range(14):
for j in range(i+1, 14):
res += s[i][j] * d[i][j]
#因为是目标函数2的希望取最大值,遗传算法也是求适应度的最大值,所以设计如下,
#乘以2000是作为罚函数的增益,保证约束条件设计值和目标函数值在差不多大小
#既返回适应度值给遗传算法,也将约束条件设计值进行返回,便于后期画目标函数收敛曲线图
return res+cs.Cons2(xy)*2000,cs.Cons2(xy)*2000
遗传算法:
from parameters import *
import constraints as cs
import obj_func as of
# 求染色体长度
def getEncodeLength(decisionvariables, delta):
# 将每个变量的编码长度放入数组
lengths = []
for decisionvar in decisionvariables:
uper = decisionvar[1]
low = decisionvar[0]
# res()返回一个数组
res = fsolve(lambda x: ((uper - low) / delta - 2 ** x + 1), 30)
# ceil()向上取整
length = int(np.ceil(res[0]))
lengths.append(length)
return lengths
# 随机生成初始化种群
def getinitialPopulation(length, populationSize):
chromsomes = np.zeros((populationSize, length), dtype=np.int)
for popusize in range(populationSize):
# np.random.randit()产生[0,2)之间的随机整数,第三个参数表示随机数的数量
chromsomes[popusize, :] = np.random.randint(0, 2, length)
return chromsomes
# 染色体解码得到表现形的解
def getDecode(population, encodelength, decisionvariables, delta):
# 得到population中有几个元素
populationsize = population.shape[0]
length = len(encodelength)
decodeVariables = np.zeros((populationsize, length), dtype=np.float)
# 将染色体拆分添加到解码数组decodeVariables中
for i, populationchild in enumerate(population):
# 设置起始点
start = 0
for j, lengthchild in enumerate(encodelength):
power = lengthchild - 1
decimal = 0
for k in range(start, start + lengthchild):
# 二进制转为十进制
decimal += populationchild[k] * (2 ** power)
power = power - 1
# 从下一个染色体开始
start = lengthchild+start
lower = decisionvariables[j][0]
uper = decisionvariables[j][1]
# 转换为表现形
decodevalue = lower + decimal * (uper - lower) / (2 ** lengthchild - 1)
# 将解添加到数组中
decodeVariables[i][j] = decodevalue
return decodeVariables
# 得到每个个体的适应度值及累计概率,目标函数1
def getFitnessValue1(decode):
# 得到种群的规模和决策变量的个数
popusize, decisionvar = decode.shape
# decisionvar=decisionvar+6
# 初始化适应度值空间和约束条件设计值空间
fitnessValue = np.zeros((popusize, 1))
consresValue = np.zeros((popusize, 1))
# 以下这两行是程序的精华,将其他两个固定位置的点和四个障碍物同样看成是要待摆放的物体,
# 同时将左上角缺的那一块看成一个长方形障碍物,作为最后一个待摆放的物体
# 记住只是看成,在实际优化计算过程中,他们的位置都是固定的,见constraints.py
for popunum in range(popusize):
six_square=np.array([24,40,62,80,74,76,12,34,42,54,49,4,5,85])
#待拜访物品和上面的进行拼接
new_decode=np.hstack((decode[popunum],six_square))
#计算适应度函数
fitnessValue[popunum][0],consresValue[popunum][0]= of.Obj_F1(new_decode)
# 得到每个个体被选择的概率
probability = fitnessValue / np.sum(fitnessValue)
# 得到每个染色体被选中的累积概率,用于轮盘赌算子使用
cum_probability = np.cumsum(probability)
return fitnessValue, cum_probability,consresValue
# 得到每个个体的适应度值及累计概率,目标函数2
def getFitnessValue2(decode):
# 得到种群的规模和决策变量的个数
popusize, decisionvar = decode.shape
# 初始化适应度值空间
fitnessValue = np.zeros((popusize, 1))
consresValue = np.zeros((popusize, 1))
for popunum in range(popusize):
six_square=np.array([24,40,62,80,74,76,12,34,42,54,49,4,5,85])
new_decode=np.hstack((decode[popunum],six_square))
fitnessValue[popunum][0],consresValue[popunum][0] = of.Obj_F2(new_decode)
# 得到每个个体被选择的概率
probability = fitnessValue / np.sum(fitnessValue)
# 得到每个染色体被选中的累积概率,用于轮盘赌算子使用
cum_probability = np.cumsum(probability)
return fitnessValue, cum_probability,consresValue
# 选择新的种群
def selectNewPopulation(decodepopu, cum_probability):
# 获取种群的规模和
m, n = decodepopu.shape
# 初始化新种群
newPopulation = np.zeros((m, n))
for i in range(m):
# 产生一个0到1之间的随机数
randomnum = np.random.random()
# 轮盘赌选择
for j in range(m):
if (randomnum < cum_probability[j]):
newPopulation[i] = decodepopu[j]
break
return newPopulation
# 新种群交叉
def crossNewPopulation(newpopu, prob):
m, n = newpopu.shape
# print(m)
# uint8将数值转换为无符号整型
numbers = np.uint8(m * prob)
# print(numbers)
# 如果选择的交叉数量为奇数,则数量加1
if numbers % 2 != 0:
numbers = numbers + 1
# 初始化新的交叉种群
updatepopulation = np.zeros((m, n), dtype=np.uint8)
# 随机生成需要交叉的染色体的索引号
index = random.sample(range(m), numbers)
# 不需要交叉的染色体直接复制到新的种群中
for i in range(m):
if not index.__contains__(i):
updatepopulation[i] = newpopu[i]
# 交叉操作
j = 0
while j < numbers:
# 随机生成一个交叉点,np.random.randint()返回的是一个列表
crosspoint = np.random.randint(0, n, 1)
crossPoint = crosspoint[0]
# a = index[j]
# b = index[j+1]
updatepopulation[index[j]][0:crossPoint] = newpopu[index[j]][0:crossPoint]
updatepopulation[index[j]][crossPoint:] = newpopu[index[j + 1]][crossPoint:]
updatepopulation[index[j + 1]][0:crossPoint] = newpopu[j + 1][0:crossPoint]
updatepopulation[index[j + 1]][crossPoint:] = newpopu[index[j]][crossPoint:]
j = j + 2
return updatepopulation
# 变异操作
def mutation(crosspopulation, mutaprob):
# 初始化变异种群
mutationpopu = np.copy(crosspopulation)
m, n = crosspopulation.shape
# 计算需要变异的基因数量
mutationnums = np.uint8(m * n * mutaprob)
# 随机生成变异基因的位置
mutationindex = random.sample(range(m * n), mutationnums)
# 变异操作
for geneindex in mutationindex:
# np.floor()向下取整返回的是float型
row = np.uint8(np.floor(geneindex / n))
colume = geneindex % n
if mutationpopu[row][colume] == 0:
mutationpopu[row][colume] = 1
else:
mutationpopu[row][colume] = 0
return mutationpopu
# 找到重新生成的种群中适应度值最大的染色体生成新种群
def findMaxPopulation(population, maxevaluation, maxSize):
#将数组转换为列表
maxevalue = maxevaluation.flatten()
maxevaluelist = maxevalue.tolist()
# 找到前20个适应度最大的染色体的索引
maxIndex = map(maxevaluelist.index, heapq.nlargest(6, maxevaluelist))
index = list(maxIndex)
colume = population.shape[1]
# 根据索引生成新的种群
maxPopulation = np.zeros((maxSize, colume))
i = 0
for ind in index:
maxPopulation[i] = population[ind]
i = i + 1
return maxPopulation
画图函数
from parameters import *
def plot_position(optimalvar):
fig1 = plt.figure(figsize = (14,8))
ax1 = fig1.add_subplot(111, aspect='equal')
plt.xlim(0,94)
plt.ylim(0,102)
#A
rect = plt.Rectangle((64,60),20,32,fill=False,edgecolor = 'black',linewidth=1)
ax1.add_patch(rect)
#B
rect = plt.Rectangle((0,0),24,68, fill=False,edgecolor = 'black',linewidth=1)
ax1.add_patch(rect)
#C
rect = plt.Rectangle((38,50),8,8,fill=False,edgecolor = 'black',linewidth=1)
ax1.add_patch(rect)
#D
rect = plt.Rectangle((24,0),50,8, fill=False,edgecolor = 'black',linewidth=1)
ax1.add_patch(rect)
#画待摆放物品
for i in range(12):
rect = plt.Rectangle((optimalvar[2*i] - F[i][0]/2, optimalvar[2*i+1] - F[i][1]/2),F[i][0],F[i][1],edgecolor="black",facecolor="blue",alpha=0.6)
ax1.add_patch(rect)
#加坐标值
for i in range(12):
str_cord="("+str(round(optimalvar[2*i],2))+","+str(round(optimalvar[2*i+1],2))+")"
plt.text(optimalvar[2*i],optimalvar[2*i+1],str_cord,fontsize=7)
#画两个固定物品,用五角星表示
plt.plot(24,40,"y*")
plt.plot(62,80,"g*")
plt.text(24,40,"(24,40)",fontsize=7)
plt.text(62,80,"(62,80)",fontsize=7)
#下面是画各种边界线
xx = np.linspace(10,94,10)
yy = 102+xx*0
plt.rcParams['lines.linewidth'] = 2
plt.plot(xx,yy,c='r')
xx = np.linspace(20,74,10)
yy = 0+xx*0
plt.rcParams['lines.linewidth'] = 2
plt.plot(xx,yy,c='r')
yy = np.linspace(68,102,10)
xx = 10+yy*0
plt.rcParams['lines.linewidth'] = 1
plt.plot(xx,yy,c='r')
yy = np.linspace(10,102,10)
xx = 94+yy*0
plt.rcParams['lines.linewidth'] = 1.5
plt.plot(xx,yy,c='r')
xx = np.linspace(0,20,10)
yy = -0.5*xx+10
plt.rcParams['lines.linewidth'] = 1
plt.plot(xx,yy,c='r')
xx = np.linspace(74,94,10)
yy = 0.5*(xx-74)
plt.rcParams['lines.linewidth'] = 1
plt.plot(xx,yy,c='r')
xx = np.linspace(0,10,10)
yy = 68+xx*0
plt.rcParams['lines.linewidth'] = 1
plt.plot(xx,yy,c='r')
yy = np.linspace(10,68,10)
xx = 0+yy*0
plt.rcParams['lines.linewidth'] = 1
plt.plot(xx,yy,c='r')
plt.xlabel("x")
plt.ylabel("y")
# plt.grid(linestyle="--")
# plt.figure()
plt.show()
将坐标值保存至excel中:
import xlsxwriter
#目标函数1的最优坐标
def save_to_excel1(optimalvar):
#生成一个excel文件
workbook = xlsxwriter.Workbook('Obj1.xlsx')
#建一个excel表
worksheet = workbook.add_worksheet()
#将A栏B栏长度设为20px
worksheet.set_column('A:A',20)
worksheet.set_column('B:B',20)
#A栏B栏第一行是名称
worksheet.write("A1","x")
worksheet.write("B1","y")
#导出坐标值
for i in range(12):
worksheet.write("A"+str(i+2),str(optimalvar[2*i]))
worksheet.write('B'+str(i+2),str(optimalvar[2*i+1]))
workbook.close() # 关闭Excel文件
#目标函数2的最优坐标
def save_to_excel2(optimalvar):
workbook = xlsxwriter.Workbook('Obj2.xlsx')
worksheet = workbook.add_worksheet()
worksheet.set_column('A:A',20)
worksheet.set_column('B:B',20)
worksheet.write("A1","x")
worksheet.write("B1","y")
for i in range(12):
worksheet.write("A"+str(i+2),str(optimalvar[2*i]))
worksheet.write('B'+str(i+2),str(optimalvar[2*i+1]))
workbook.close() # 关闭Excel文件
主函数:
from parameters import *
#导入约束条件模块
import constraints as cs
#导入遗传算法模块
import GA
# 导入目标函数模块
import obj_func as of
# 导入画图模块
import plot_objects as po
# 导入时间模块
import time
# 导入保存进excel模块
import save_to_excel as ste
# 两个决策变量的上下界,多维数组之间必须加逗号
decisionVariables = cs.Cons1()
# 精度,用于将坐标值放大后转化成二进制码,不设置的话精度会只能用很短的二进制码来表示,比如10——>1010,太短不适合遗传算法
delta = 0.0001
# 获取染色体长度,放大之后为20位
EncodeLength = GA.getEncodeLength(decisionVariables, delta)
# 种群数量,设成100也行,大了耗时间,效果还不一定好,没必要
initialPopuSize = 6
# 初始随机生成6个种群,也就是6个种群,每个种群长度为12x2x20(待拜访物品个数12个,2个坐标x,y,每个坐标值表示成20为的二进制码)
population = GA.getinitialPopulation(sum(EncodeLength), initialPopuSize)
#最大进化代数,设成500也行,太大没必要,已经提前收敛了
maxgeneration = 600
# 交叉概率,大小影响不大
prob = 1
# 变异概率,大小影响不大
mutationprob = 1
# 新生成的种群数量
maxPopuSize = 6
#先往下看
optimalvalue = []
cons_resvalue = []
optimalvariables = []
print("为了生成约束条件下使得目标函数1最小值的染色体,计划繁殖",maxgeneration,"代,繁殖开始:")
#记录程序执行时间,睡2秒只是为了滚起来不那么突兀
time.sleep(2) #延时2s
starttime = time.time()
#求解目标函数2
for generation in range(maxgeneration):
if generation==0:
print(">>第",generation+1,"代正在繁殖中...")
if generation>0 and generation%100==0:
print(">>第",generation,"代正在繁殖中...")
if generation>maxgeneration-11:
print(">>第",generation+1,"代正在繁殖中...")
# 对种群解码得到表现形,二进制转十进制
decode = GA.getDecode(population, EncodeLength, decisionVariables, delta)
# 得到适应度值和累计概率值,先计算第一个目标函数,因此设计适应度值为:约束条件设计值-目标函数值,越大越好
evaluation, cum_proba,cons_res = GA.getFitnessValue1(decode)
# 选择新的种群,轮盘赌算法,具体可参考之前相关链接
newpopulations = GA.selectNewPopulation(population, cum_proba)
# 新种群交叉
crossPopulations = GA.crossNewPopulation(newpopulations, prob)
# 变异操作
mutationpopulation = GA.mutation(crossPopulations, mutationprob)
# 将父母和子女合并为新的种群
totalpopulation = np.vstack((population, mutationpopulation))
# 最终解码
final_decode = GA.getDecode(totalpopulation, EncodeLength, decisionVariables, delta)
# 适应度评估
final_evaluation, final_cumprob,cons_res = GA.getFitnessValue1(final_decode)
#选出适应度最大的6个重新生成种群
population = GA.findMaxPopulation(totalpopulation, final_evaluation, maxPopuSize)
# 找到本轮中适应度最大的值
index = np.where(final_evaluation == max(final_evaluation))
# 分别保存最大适应度的值,最大适应度对应的约束条件设计值,最大适应度对应的染色体编码表现形解
for i in range(len(index[0])):
optimalvalue.append(np.max(final_evaluation))#最大适应度的值
cons_resvalue.append(cons_res[index[0][i]])#最大适应度对应的约束条件设计值
optimalvariables.append(list(final_decode[index[0][i]]))#最大适应度对应的染色体编码表现形解
#得到计算第一个目标函数最有值的最终运行时间
endtime = time.time()
dtime = endtime - starttime
# 画出每个迭代环节最小目标函数值对应的收敛曲线图
x = [i for i in range(maxgeneration)]
# 此处要用适应度负值加约束条件值才是真正的目标函数值
y = [-optimalvalue[i]+cons_resvalue[i] for i in range(maxgeneration)]
plt.plot(x, y)
plt.show()
#找出一共有多少个染色体达到了相同的最大适应度值
index = np.where(optimalvalue == max(optimalvalue))
print(round(dtime),"秒过去了,繁殖完成!共生成约束条件下使得目标函数2最大值的染色体",len(index[0]),"个")
#取满足最大适应度值的染色体序列里的第一个,取哪个都无所谓,反正适应度值都一样
optimalvar = optimalvariables[index[0][0]]
#保存进excel
ste.save_to_excel1(optimalvar)
#画布置图
po.plot_position(optimalvar)
#以下程序是对目标函数2最大值的求解过程,如果看不懂,参考上面注释
#最大进化代数
maxgeneration = 200
optimalvalue = []
optimalvariables = []
cons_resvalue = []
print("\n为了生成约束条件下使得目标函数2最大值的染色体,计划繁殖",maxgeneration,"代,繁殖开始:")
time.sleep(2) #延时2s
starttime = time.time()
#求解目标函数2
for generation in range(maxgeneration):
if generation==0:
print(">>第",generation+1,"代正在繁殖中...")
if generation>0 and generation%100==0:
print(">>第",generation,"代正在繁殖中...")
if generation>maxgeneration-11:
print(">>第",generation+1,"代正在繁殖中...")
# 对种群解码得到表现形
decode = GA.getDecode(population, EncodeLength, decisionVariables, delta)
# 得到适应度值和累计概率值
evaluation, cum_proba,cons_res = GA.getFitnessValue2(decode)
# 选择新的种群
newpopulations = GA.selectNewPopulation(population, cum_proba)
# 新种群交叉
crossPopulations = GA.crossNewPopulation(newpopulations, prob)
# 变异操作
mutationpopulation = GA.mutation(crossPopulations, mutationprob)
# 将父母和子女合并为新的种群
totalpopulation = np.vstack((population, mutationpopulation))
# 最终解码
final_decode = GA.getDecode(totalpopulation, EncodeLength, decisionVariables, delta)
# 适应度评估
final_evaluation, final_cumprob,cons_res = GA.getFitnessValue2(final_decode)
#选出适应度最大的6个重新生成种群
population = GA.findMaxPopulation(totalpopulation, final_evaluation, maxPopuSize)
# 找到本轮中适应度最大的值
index = np.where(final_evaluation == max(final_evaluation))
for i in range(len(index[0])):
optimalvalue.append(np.max(final_evaluation))
cons_resvalue.append(cons_res[index[0][i]])
optimalvariables.append(list(final_decode[index[0][i]]))#list增加了位数
endtime = time.time()
dtime = endtime - starttime
# 输出最后一个最大适应度值对应的染色体编号
x = [i for i in range(maxgeneration)]
y = [optimalvalue[i]-cons_resvalue[i] for i in range(maxgeneration)]
plt.plot(x, y)
plt.show()
index = np.where(optimalvalue == max(optimalvalue))
print(round(dtime),"秒过去了!共生成约束条件下使得目标函数2最大值的染色体",len(index[0]),"个")
optimalvar = optimalvariables[index[0][0]]
ste.save_to_excel2(optimalvar)
po.plot_position(optimalvar)
输出结果:
为了生成约束条件下使得目标函数1最小值的染色体,计划繁殖 600 代,繁殖开始:
>>第 1 代正在繁殖中...
>>第 100 代正在繁殖中...
>>第 200 代正在繁殖中...
>>第 300 代正在繁殖中...
>>第 400 代正在繁殖中...
>>第 500 代正在繁殖中...
>>第 591 代正在繁殖中...
>>第 592 代正在繁殖中...
>>第 593 代正在繁殖中...
>>第 594 代正在繁殖中...
>>第 595 代正在繁殖中...
>>第 596 代正在繁殖中...
>>第 597 代正在繁殖中...
>>第 598 代正在繁殖中...
>>第 599 代正在繁殖中...
>>第 600 代正在繁殖中...
37 秒过去了,繁殖完成!共生成约束条件下使得目标函数2最大值的染色体 3 个
为了生成约束条件下使得目标函数2最大值的染色体,计划繁殖 200 代,繁殖开始:
>>第 1 代正在繁殖中...
>>第 100 代正在繁殖中...
>>第 191 代正在繁殖中...
>>第 192 代正在繁殖中...
>>第 193 代正在繁殖中...
>>第 194 代正在繁殖中...
>>第 195 代正在繁殖中...
>>第 196 代正在繁殖中...
>>第 197 代正在繁殖中...
>>第 198 代正在繁殖中...
>>第 199 代正在繁殖中...
>>第 200 代正在繁殖中...
12 秒过去了!共生成约束条件下使得目标函数2最大值的染色体 1 个
[Finished in 219.6s]
输出图像: