当前位置: 首页 > news >正文

启发式搜索--模拟退火算法 matlab

一、背景

贪心算法失效:陷入局部最优

二、思想

该点位置高,直接去;位置低,利用距离决定是否去

三、关键点

1.设置temperature,使跳动结束

2.设置概率函数,使到最优解的概率最大

四、适用赛题:可行解过多、NP-hard问题

Q1.求给定函数最值问题

1.一元函数

产生新解:找附近的一个x值,生成对应的fx,进行比较

%% SA 模拟退火: 求解函数y = 11*sin(x) + 7*cos(5*x)在[-3,3]内的最大值(动画演示)
tic
clear; clc%% 绘制函数的图形
x = -3:0.1:3;
y = 11*sin(x) + 7*cos(5*x);
figure
plot(x,y,'b-')
hold on  % 不关闭图形,继续在上面画图%% 参数初始化
narvs = 1; % 变量个数
T0 = 100;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 200;  % 最大迭代次数
Lk = 100;  % 每个温度下的迭代次数
alfa = 0.95;  % 温度衰减系数
x_lb = -3; % x的下界
x_ub = 3; % x的上界%%  随机生成一个初始解
x0 = zeros(1,narvs);
for i = 1: narvsx0(i) = x_lb(i) + (x_ub(i)-x_lb(i))*rand(1);    
end
y0 = Obj_fun1(x0); % 计算当前解的函数值
h = scatter(x0,y0,'*r');  % scatter是绘制二维散点图的函数(这里返回h是为了得到图形的句柄,未来我们对其位置进行更新)%% 定义一些保存中间过程的量,方便输出结果和画图
max_y = y0;     % 初始化找到的最佳的解对应的函数值为y0
MAXY = zeros(maxgen,1); % 记录每一次外层循环结束后找到的max_y (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  % 内循环,在每个温度下开始迭代y = randn(1,narvs);  % 生成1行narvs列的N(0,1)随机数z = y / sqrt(sum(y.^2)); % 根据新解的产生规则计算zx_new = x0 + z*T; % 根据新解的产生规则计算x_new的值% 如果这个新解的位置超出了定义域,就对其进行调整for j = 1: narvsif x_new(j) < x_lb(j)r = rand(1);x_new(j) = r*x_lb(j)+(1-r)*x0(j);elseif x_new(j) > x_ub(j)r = rand(1);x_new(j) = r*x_ub(j)+(1-r)*x0(j);endendx1 = x_new;    % 将调整后的x_new赋值给新解x1y1 = Obj_fun1(x1);  % 计算新解的函数值if y1 > y0    % 如果新解函数值大于当前解的函数值x0 = x1; % 更新当前解为新解y0 = y1;elsep = exp(-(y0 - y1)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率x0 = x1; % 更新当前解为新解y0 = y1;endend% 判断是否要更新找到的最佳的解if y0 > max_y  % 如果当前解更好,则对其进行更新max_y = y0;  % 更新最大的ybest_x = x0;  % 更新找到的最好的xendendMAXY(iter) = max_y; % 保存本轮外循环结束后找到的最大的yT = alfa*T;   % 温度下降pause(0.01)  % 暂停一段时间(单位:秒)后再接着画图h.XData = x0;  % 更新散点图句柄的x轴的数据(此时解的位置在图上发生了变化)h.YData = Obj_fun1(x0); % 更新散点图句柄的y轴的数据(此时解的位置在图上发生了变化)
enddisp('最佳的位置是:'); disp(best_x)
disp('此时最优值是:'); disp(max_y)pause(0.5)
h.XData = [];  h.YData = [];  % 将原来的散点删除
scatter(best_x,max_y,'*r');  % 在最大值处重新标上散点
title(['模拟退火找到的最大值为', num2str(max_y)])  % 加上图的标题%% 画出每次迭代后找到的最大y的图形
figure
plot(1:maxgen,MAXY,'b-');
xlabel('迭代次数');
ylabel('y的值');
toc

2.二元函数

%% SA 模拟退火: 求解函数y = x1^2+x2^2-x1*x2-10*x1-4*x2+60在[-15,15]内的最小值(动画演示)
ticclear; clc
%% 绘制函数的图形
figure 
x1 = -15:1:15;
x2 = -15:1:15;
[x1,x2] = meshgrid(x1,x2);
y = x1.^2 + x2.^2 - x1.*x2 - 10*x1 - 4*x2 + 60;
mesh(x1,x2,y)
xlabel('x1');  ylabel('x2');  zlabel('y');  % 加上坐标轴的标签
axis vis3d % 冻结屏幕高宽比,使得一个三维对象的旋转不会改变坐标轴的刻度显示
hold on  % 不关闭图形,继续在上面画图%% 参数初始化
narvs = 2; % 变量个数
T0 = 100;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 200;  % 最大迭代次数
Lk = 100;  % 每个温度下的迭代次数
alfa = 0.95;  % 温度衰减系数
x_lb = [-15 -15]; % x的下界
x_ub = [15 15]; % x的上界%%  随机生成一个初始解
x0 = zeros(1,narvs);
for i = 1: narvsx0(i) = x_lb(i) + (x_ub(i)-x_lb(i))*rand(1);    
end
y0 = Obj_fun2(x0); % 计算当前解的函数值
h = scatter3(x0(1),x0(2),y0,'*r');  % scatter3是绘制三维散点图的函数(这里返回h是为了得到图形的句柄,未来我们对其位置进行更新)%% 定义一些保存中间过程的量,方便输出结果和画图
min_y = y0;     % 初始化找到的最佳的解对应的函数值为y0
MINY = zeros(maxgen,1); % 记录每一次外层循环结束后找到的min_y (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  % 内循环,在每个温度下开始迭代y = randn(1,narvs);  % 生成1行narvs列的N(0,1)随机数z = y / sqrt(sum(y.^2)); % 根据新解的产生规则计算zx_new = x0 + z*T; % 根据新解的产生规则计算x_new的值% 如果这个新解的位置超出了定义域,就对其进行调整for j = 1: narvsif x_new(j) < x_lb(j)r = rand(1);x_new(j) = r*x_lb(j)+(1-r)*x0(j);elseif x_new(j) > x_ub(j)r = rand(1);x_new(j) = r*x_ub(j)+(1-r)*x0(j);endendx1 = x_new;    % 将调整后的x_new赋值给新解x1y1 = Obj_fun2(x1);  % 计算新解的函数值if y1 < y0    % 如果新解函数值小于当前解的函数值x0 = x1; % 更新当前解为新解y0 = y1;elsep = exp(-(y1 - y0)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率x0 = x1;  % 更新当前解为新解y0 = y1;endend% 判断是否要更新找到的最佳的解if y0 < min_y  % 如果当前解更好,则对其进行更新min_y = y0;  % 更新最小的ybest_x = x0;  % 更新找到的最好的xendendMINY(iter) = min_y; % 保存本轮外循环结束后找到的最小的yT = alfa*T;   % 温度下降pause(0.02)  % 暂停一段时间后(单位:秒)再接着画图h.XData = x0(1);  % 更新散点图句柄的x轴的数据(此时解的位置在图上发生了变化)h.YData = x0(2); % 更新散点图句柄的y轴的数据(此时解的位置在图上发生了变化)h.ZData = Obj_fun2(x0);  % 更新散点图句柄的z轴的数据(此时粒子的位置在图上发生了变化)
enddisp('最佳的位置是:'); disp(best_x)
disp('此时最优值是:'); disp(min_y)pause(0.5) 
h.XData = [];  h.YData = [];  h.ZData = [];  % 将原来的散点删除
scatter3(best_x(1), best_x(2), min_y,'*r');  % 在最小值处重新标上散点
title(['模拟退火找到的最小值为', num2str(min_y)])  % 加上图的标题%% 画出每次迭代后找到的最小y的图形
figure
plot(1:maxgen,MINY,'b-');
xlabel('迭代次数');
ylabel('y的值');
toc

Q2:旅行商问题(Traveling Saleman Problem,TSP)

给定一系列城市和没对城市之间的距离,访问每一座城市再回到初始城市的最短回路

三种产生新解的方法:交换法、移位法、倒置法

%% 模拟退火解决TSP问题tic
rng('shuffle')  % 控制随机数的生成,否则每次打开matlab得到的结果都一样
% https://ww2.mathworks.cn/help/matlab/math/why-do-random-numbers-repeat-after-startup.html
% https://ww2.mathworks.cn/help/matlab/ref/rng.html
clear;clc
% 38个城市,TSP数据集网站(http://www.tsp.gatech.edu/world/djtour.html) 上公测的最优结果6656。
coord = [11003.611100,42102.500000;11108.611100,42373.888900;11133.333300,42885.833300;11155.833300,42712.500000;11183.333300,42933.333300;11297.500000,42853.333300;11310.277800,42929.444400;11416.666700,42983.333300;11423.888900,43000.277800;11438.333300,42057.222200;11461.111100,43252.777800;11485.555600,43187.222200;11503.055600,42855.277800;11511.388900,42106.388900;11522.222200,42841.944400;11569.444400,43136.666700;11583.333300,43150.000000;11595.000000,43148.055600;11600.000000,43150.000000;11690.555600,42686.666700;11715.833300,41836.111100;11751.111100,42814.444400;11770.277800,42651.944400;11785.277800,42884.444400;11822.777800,42673.611100;11846.944400,42660.555600;11963.055600,43290.555600;11973.055600,43026.111100;12058.333300,42195.555600;12149.444400,42477.500000;12286.944400,43355.555600;12300.000000,42433.333300;12355.833300,43156.388900;12363.333300,43189.166700;12372.777800,42711.388900;12386.666700,43334.722200;12421.666700,42895.555600;12645.000000,42973.333300];
n = size(coord,1);  % 城市的数目figure  % 新建一个图形窗口
plot(coord(:,1),coord(:,2),'o');   % 画出城市的分布散点图
hold on % 等一下要接着在这个图形上画图的d = zeros(n);   % 初始化两个城市的距离矩阵全为0
for i = 2:n  for j = 1:i  coord_i = coord(i,:);   x_i = coord_i(1);     y_i = coord_i(2);  % 城市i的横坐标为x_i,纵坐标为y_icoord_j = coord(j,:);   x_j = coord_j(1);     y_j = coord_j(2);  % 城市j的横坐标为x_j,纵坐标为y_jd(i,j) = sqrt((x_i-x_j)^2 + (y_i-y_j)^2);   % 计算城市i和j的距离end
end
d = d+d';   % 生成距离矩阵的对称的一面%% 参数初始化
T0 = 1000;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 1000;  % 最大迭代次数
Lk = 500;  % 每个温度下的迭代次数
alpfa = 0.95;  % 温度衰减系数%%  随机生成一个初始解
path0 = randperm(n);  % 生成一个1-n的随机打乱的序列作为初始的路径
result0 = calculate_tsp_d(path0,d); % 调用我们自己写的calculate_tsp_d函数计算当前路径的距离%% 定义一些保存中间过程的量,方便输出结果和画图
min_result = result0;     % 初始化找到的最佳的解对应的距离为result0
RESULT = zeros(maxgen,1); % 记录每一次外层循环结束后找到的min_result (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  %  内循环,在每个温度下开始迭代path1 = gen_new_path(path0);  % 调用我们自己写的gen_new_path函数生成新的路径result1 = calculate_tsp_d(path1,d); % 计算新路径的距离%如果新解距离短,则直接把新解的值赋值给原来的解if result1 < result0    path0 = path1; % 更新当前路径为新路径result0 = result1; elsep = exp(-(result1 - result0)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率path0 = path1;  % 更新当前路径为新路径result0 = result1; endend% 判断是否要更新找到的最佳的解if result0 < min_result  % 如果当前解更好,则对其进行更新min_result = result0;  % 更新最小的距离best_path = path0;  % 更新找到的最短路径endendRESULT(iter) = min_result; % 保存本轮外循环结束后找到的最小距离T = alpfa*T;   % 温度下降       
enddisp('最佳的方案是:'); disp(mat2str(best_path))
disp('此时最优值是:'); disp(min_result)best_path = [best_path,best_path(1)];   % 在最短路径的最后面加上一个元素,即第一个点(我们要生成一个封闭的图形)
n = n+1;  % 城市的个数加一个(紧随着上一步)
for i = 1:n-1 j = i+1;coord_i = coord(best_path(i),:);   x_i = coord_i(1);     y_i = coord_i(2); coord_j = coord(best_path(j),:);   x_j = coord_j(1);     y_j = coord_j(2);plot([x_i,x_j],[y_i,y_j],'-b')    % 每两个点就作出一条线段,直到所有的城市都走完
%     pause(0.02)  % 暂停0.02s再画下一条线段hold on
end%% 画出每次迭代后找到的最短路径的图形
figure
plot(1:maxgen,RESULT,'b-');
xlabel('迭代次数');
ylabel('最短路径');toc
% calculate_tsp_d.mfunction  result =  calculate_tsp_d(path,d)
% 输入:path:路径(1至n的一个序列),d:距离矩阵n = length(path);result = 0; % 初始化该路径走的距离为0for i = 1:n-1  result = d(path(i),path(i+1)) + result;  % 按照这个序列不断的更新走过的路程这个值end   result = d(path(1),path(n)) + result;  % 别忘了加上从最后一个城市返回到最开始那个城市的距离
end

Q3:书店买书问题(0-1规划)

 15书店,20本书,书店运费在最后一列,怎样选择买书方案

data:

产生新解的方法:随机选择一家书店进行更换

%% 模拟退火解决书店买书问题  % 466
tic
rng('shuffle')  % 控制随机数的生成,否则每次打开matlab得到的结果都一样load book_data  % 这个文件一定要在当前文件夹下面
% 这个数据文件里面保存了两个矩阵:M是每本书在每家店的价格; freight表示每家店的运费
[s, b] = size(M);  % s是书店的数量,b是要购买的书的数量%% 参数初始化
T0 = 1000;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 500;  % 最大迭代次数
Lk = 200;  % 每个温度下的迭代次数
alfa = 0.95;  % 温度衰减系数%%  随机生成一个初始解
way0 = randi([1, s],1,b); % 在1-s这些整数中随机抽取一个1*b的向量,表示这b本书分别在哪家书店购买
money0 = calculate_money(way0,freight,M,b); % 调用我们自己写的calculate_money函数计算这个方案的花费%% 定义一些保存中间过程的量,方便输出结果和画图
min_money = money0;     % 初始化找到的最佳的解对应的花费为money0
MONEY = zeros(maxgen,1); % 记录每一次外层循环结束后找到的min_money (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  %  内循环,在每个温度下开始迭代way1 = gen_new_way(way0,s,b);  % 调用我们自己写的gen_new_way函数生成新的方案money1 = calculate_money(way1,freight,M,b); % 计算新方案的花费if money1 < money0    % 如果新方案的花费小于当前方案的花费way0 = way1; % 更新当前方案为新方案money0 = money1;elsep = exp(-(money1 - money0)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率way0 = way1;money0 = money1;endend% 判断是否要更新找到的最佳的解if money0 < min_money  % 如果当前解更好,则对其进行更新min_money = money0;  % 更新最小的花费best_way = way0;  % 更新找到的最佳方案endendMONEY(iter) = min_money; % 保存本轮外循环结束后找到的最小花费T = alfa*T;   % 温度下降
enddisp('最佳的方案是:'); disp(mat2str(best_way))
disp('此时最优值是:'); disp(min_money)%% 画出每次迭代后找到的最佳方案的图形
figure
plot(1:maxgen,MONEY,'b-');
xlabel('迭代次数');
ylabel('最小花费');
toc
% calculate_money.mfunction  money =  calculate_money(way,freight,M,b)
% 输入:way: 购买方案; fright:运费;  M: 每本书在每家店的价格; b:一共要购买几本书index = unique(way);  % 在哪些商店购买了商品,因为我们等下要计算运费money = sum(freight(index)); % 计算买书花费的运费% 计算总花费:刚刚计算出来的运费 + 五本书的售价for i = 1:b money = money + M(way(i),i);  end
end

Q4:背包问题(整数规划)

%% 模拟退火求解背包问题,本题的最优解是2410
% 因为这题只有十个物品,用枚举法其实也能做出来
% 建模中遇到了背包问题还是用intlinprog函数哦~这题只是训练大家的编程和建模的思维profit = [540 200 180 350 60 150 280 450 320 120];  % 每件物品的利润
weight = [6 3 4 5 1 2 3 5 4 2];  % 每件物品的重量
max_weight = 30;  % 最大装载重量 
n = length(profit); % 物品个数%% 参数初始化
T0 = 1000;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 500;  % 最大迭代次数
Lk = 200;  % 每个温度下的迭代次数
alfa = 0.95;  % 温度衰减系数%%  生成初始解
way0 = zeros(1,n); % 初始解中每个元素都为0,表示一件物品都不装
profit0 = sum(way0 .* profit); % 计算这个装载方案的利润%% 定义一些保存中间过程的量,方便输出结果和画图
max_profit = profit0;     % 初始化找到的最佳的解对应的利润为profit0
PROFIT = zeros(maxgen,1); % 记录每一次外层循环结束后找到的max_profit (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  %  内循环,在每个温度下开始迭代       weight0 = sum(way0 .* weight); % 计算这个装载方案的重量[way1, delta_weight] = gen_new_way(way0, n, weight);  % 调用我们自己写的gen_new_way函数生成新的装载方案profit1 = sum(way1 .* profit); % 计算新装载方案的利润if weight0 + delta_weight > max_weight    % 如果超重了,就不操作[];  % 空语句,相当于啥都不干elseif profit1 > profit0  % 如果没有超重,而且新装载方案的利润更高way0 = way1; % 更新当前装载方案为新装载方案profit0 = profit1;elsep = exp(-(profit0 - profit1)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率way0 = way1;  % 更新当前装载方案为新装载方案profit0 = profit1;endend% 判断是否要更新找到的最佳的解if profit0 > max_profit  % 如果当前解更好,则对其进行更新max_profit = profit0;  % 更新最大的利润best_way = way0;  % 更新找到的最好的装载方案endendPROFIT(iter) = max_profit; % 保存本轮外循环结束后找到的最大的利润T = alfa*T;   % 温度下降       
enddisp('最佳的方案是:'); disp(best_way)
disp('此时最优值是:'); disp(max_profit)
function [way1, delta_weight] = gen_new_way(way0, n, weight)
% way0:原来的装载方案;  n是物品个数  ; weight是物品的重量
% way1:新的装载方案; delta_weight:重量的变化量i = randi([1,n],1);  % 随机选取一个物品iif way0(i) == 1  % 如果物品i在原来的背包中way0(i) = 0;  % 从背包里取出物品iempty_ind = find(way0==0); % 看看背包中哪几个位置是空的length_empth_ind = length(empty_ind);  % 计算空位置的个数ind = randi([1, length_empth_ind], 1); % 在这几个空位置中取一个随机下标 j = empty_ind(ind);  % j就是随机选择出来的背包中的某个空位置way0(j) = 1;  % 装入物品jdelta_weight = weight(j) - weight(i);  % 计算重量的变化量else  % 如果物品i原来就不在背包中way0(i) = 1; % 在背包中放入物品idelta_weight = weight(i);  % 计算重量的变化量if rand(1) < 0.5 % 判断是否需要再取出一个物品(这里的0.5是需要再取出物品的概率,可以自己调整)fill_ind = find(way0==1); % 看看背包中哪几个位置有物品length_fill_ind = length(fill_ind);  % 计算有物品的位置的个数ind = randi([1, length_fill_ind], 1); % 在这几个有物品的位置中取一个随机下标 j = fill_ind(ind);  % j就是随机选择出来的背包中的某个有物品的位置way0(j) = 0;  % 取出物品jdelta_weight = weight(i) - weight(j);  % 计算重量的变化量endendway1 = way0;  % 将调整后的way0赋值给way1
end

eg:寝室同学兴趣爱好问题

题目:40名同学 需要分到 10个寝室,我们通过调查问卷得到了这 40 名同 学的兴趣爱好,请问怎么划分 寝室 能够保证 :不同寝室间, 同寝室 同学的 共爱好数量分布尽 可能 均匀 。

思路:先计算出同学们两两爱好数量关系,之后利用模拟退火进行方差最小的优化

数据预处理

import numpy as np 
import pandas as pd 
df = pd.read_csv(r'data.csv') 
data = df.iloc[:,1].tolist() 
data = [set(i.replace('其他','').strip('、').split('、')) for i in data]、
# 去掉 ‘其他’ 和‘、’ 然后对爱好进行进行切割 ,之后转化为集合
result = [len(i & j)  for i in data for j in data] # 求交集个数
result = np.array(result).reshape(len(data),-1) # 转化为40*40的矩阵
np.savetxt(r'mydata.csv', result, delimiter=',') 

模拟退火

% main.mclear;clc
tic
rng('shuffle')  % 控制随机数的生成,否则每次打开matlab得到的结果都一样
% https://ww2.mathworks.cn/help/matlab/math/why-do-random-numbers-repeat-after-startup.html
% https://ww2.mathworks.cn/help/matlab/ref/rng.html
n = 40;  % 有多少名同学
mydata = csvread('mydata.csv');%% 参数初始化
T0 = 1000;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 500;  % 最大迭代次数
Lk = 500;  % 每个温度下的迭代次数
alpfa = 0.95;  % 温度衰减系数%%  随机生成一个初始解
path0 = randperm(n);
result0 = calculate_ans(path0,mydata);  % 计算这一组解对应的标准差%% 定义一些保存中间过程的量,方便输出结果和画图
min_result = result0;    
RESULT = zeros(maxgen,1); % 记录每一次外层循环结束后找到的min_result (方便画图)%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数for i = 1 : Lk  %  内循环,在每个温度下开始迭代path1 = gen_new_path(path0);  result1 = calculate_ans(path1,mydata); if result1 < result0    path0 = path1; result0 = result1; elsep = exp(-(result1 - result0)/T); % 根据Metropolis准则计算一个概率if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率path0 = path1;  result0 = result1; endend% 判断是否要更新找到的最佳的解if result0 < min_result  % 如果当前解更好,则对其进行更新min_result = result0;  best_path = path0;  endendRESULT(iter) = min_result; % 保存本轮外循环结束后找到的最小的结果T = alpfa*T;   % 温度下降       
enddisp('最佳的方案是:'); disp(reshape(best_path,4,n/4))
disp('此时最优值是:'); disp(min_result)%% 画出每次迭代后找到的图形
figure
plot(1:maxgen,RESULT,'b-');
xlabel('迭代次数');[~,tmp] = calculate_ans(best_path,mydata)  % 前面的~表示不需要第一个返回结果
toc
% calculate_ans.mfunction [ans,tmp] = calculate_ans(path,mydata)n = length(path);  % 学生个数nums = n  / 4;   % 寝室个数path = reshape(path,4,nums);  % 每四个人分配到一个寝室tmp = zeros(1,nums);  % tmp用来保存每个寝室的共同爱好数for i = 1 : numstmp(i) = get_total_hobby(path(:,i),mydata);  % 调用子函数单独计算每个寝室四名同学的共同爱好数end
%     ans = std(tmp);   % 计算标准差ans = (std(tmp) + 1)  / max(tmp);
%     ans = (std(tmp) + 1)  / mean(tmp);
end
% get_total_hobby.mfunction hobby = get_total_hobby(path,mydata)
% path: 同寝室四名同学的编号
% mydata: 每两个同学之间的共同爱好数hobby = 0;for i = 1 : 4for j = 1:iif i ~= jhobby = hobby+mydata(path(i), path(j));endendend
end
% gen_new_path.mfunction path1 = gen_new_path(path0)% path0: 原来的路径n = length(path0);% 随机选择两种产生新路径的方法p1 = 0.33;  % 使用交换法产生新路径的概率p2 = 0.33;  % 使用移位法产生新路径的概率r = rand(1); % 随机生成一个[0 1]间均匀分布的随机数if  r< p1    % 使用交换法产生新路径 c1 = randi(n);   % 生成1-n中的一个随机整数c2 = randi(n);   % 生成1-n中的一个随机整数path1 = path0;  % 将path0的值赋给path1path1(c1) = path0(c2);  %改变path1第c1个位置的元素为path0第c2个位置的元素path1(c2) = path0(c1);  %改变path1第c2个位置的元素为path0第c1个位置的元素elseif r < p1+p2 % 使用移位法产生新路径c1 = randi(n);   % 生成1-n中的一个随机整数c2 = randi(n);   % 生成1-n中的一个随机整数c3 = randi(n);   % 生成1-n中的一个随机整数sort_c = sort([c1 c2 c3]);  % 对c1 c2 c3从小到大排序c1 = sort_c(1);  c2 = sort_c(2);  c3 = sort_c(3);  % c1 < = c2 <=  c3tem1 = path0(1:c1-1);tem2 = path0(c1:c2);tem3 = path0(c2+1:c3);tem4 = path0(c3+1:end);path1 = [tem1 tem3 tem2 tem4];else  % 使用倒置法产生新路径c1 = randi(n);   % 生成1-n中的一个随机整数c2 = randi(n);   % 生成1-n中的一个随机整数if c1>c2  % 如果c1比c2大,就交换c1和c2的值tem = c2;c2 = c1;c1 = tem;endtem1 = path0(1:c1-1);tem2 = path0(c1:c2);tem3 = path0(c2+1:end);path1 = [tem1 fliplr(tem2) tem3];   %矩阵的左右对称翻转 fliplr,上下对称翻转 flipudend
end

五、注意

1.一定能找到最优解吗?

可以利用马尔科夫过程进行证明

2.参数的选择

3.新解的构造

4.算法之间的相互比较

遗传、粒子群、蚁群


文章转载自:

http://p48ez2Om.trsxw.cn
http://Qq6UvRsF.trsxw.cn
http://Z447Nx1I.trsxw.cn
http://cmQpESRY.trsxw.cn
http://vXeqkH3d.trsxw.cn
http://4mmtAdSH.trsxw.cn
http://KukV4kcV.trsxw.cn
http://hdtjggcR.trsxw.cn
http://0JKUvA3T.trsxw.cn
http://M4vCeWdn.trsxw.cn
http://zQa8w9Fh.trsxw.cn
http://YW2cy5Fe.trsxw.cn
http://T1XWk93M.trsxw.cn
http://nNIKegU4.trsxw.cn
http://on5o2SdZ.trsxw.cn
http://YBygNlRw.trsxw.cn
http://bQaTScJV.trsxw.cn
http://Z114yR9C.trsxw.cn
http://ZaILkOI6.trsxw.cn
http://BBOzwWXK.trsxw.cn
http://B2ZcmQjK.trsxw.cn
http://PUXFl3DD.trsxw.cn
http://O2dBDaKu.trsxw.cn
http://PF4AXISH.trsxw.cn
http://U6HlBHyy.trsxw.cn
http://SH6KEktF.trsxw.cn
http://JUgW4EvI.trsxw.cn
http://lYVOatqt.trsxw.cn
http://OkYdqXGO.trsxw.cn
http://BkFmLKmZ.trsxw.cn
http://www.dtcms.com/a/386785.html

相关文章:

  • 论文阅读:arixv 2025 One Token to Fool LLM-as-a-Judge
  • 【C++入门】C++基础
  • 10 正则表达式
  • 本地文件->RTSP->HLS->网页播放
  • 148.排序链表,23.合并K个升序链表
  • 思特威CMOS sensor rbrow寄存器设置需要注意的事项(二)
  • 物联网精准节能平台:工厂“数字大脑”如何让节能更智能?
  • Java进阶教程,全面剖析Java多线程编程,实现Callable接口实现多线程,笔记05
  • Windows Server Web 服务器安全防护(开放 HTTP端口,限制恶意 IP)
  • 深度学习:从预备知识到未来展望
  • 数据库(五)MySQL的数据备份
  • linux的tar命令详细使用
  • 德克西尔断链保护器:守护工业生产的“安全屏障”
  • 自动化脚本的核心引擎
  • 【LeetCode 每日一题】3025. 人员站位的方案数 I——(解法一)暴力枚举
  • α-β-γ 滤波器推导(例 1:均值滤波的递推形式)
  • el-upload上传文件自定义
  • 只有select权限,确实也可以for update锁表
  • HBase核心知识点总结
  • Springboot 使用缓存cache
  • 基于边缘计算的智能管控终端充电站有序充电系统设计与实现 —— 面向实时功率调度需求
  • Nordic BLE智能门锁应用
  • IDEA 连接MySQL数据导出和导入指南
  • 在window下使用visual studio + cmake gui 源码编译 gRPC
  • C# halcon 拼图例子
  • 网络:常见的高速网卡(100Gbps和400Gbps)
  • 第十四届蓝桥杯青少组C++选拔赛[2022.12.18]第二部分编程题(4、充电站)
  • 华为P10plus adb 无线调试USB拔除后立即失效解决
  • openharmony 鸿蒙 下 利用蓝牙API(a2dp模块-高级音频,ble模块-低功耗蓝牙等)完成对蓝牙音响的控制(蓝牙广播)
  • 软考-系统架构设计师 需求工程详细讲解