遇到的问题1:在运行主程序一次后,得出的TCPSO中的粒子和适应度值出了问题,粒子每个维度都是上下限,并且得到的适应度值和文章最后得到的适应度值0相差比较大,修改了很多次速度,没什么用,如下图(图中右边是我设置的TCPSO的初始化参数)
但是当我把维度上下限变大之后,粒子的每个维度也随之增大近乎无穷大,而适应度值和文章要求的0越来越接近,如下图(图中右边是我设置的TCPSO的初始化参数)
而且每次都是在运行完主程序的第一代,也就是TCPSO运行max_iter后,得出了最佳粒子和适应度值,之后每次都是这个适应度值,不会改变。
遇到的问题2:我对文章以及文章的结论不太理解
1、我目前用的是Sphere当作了目标函数值,一般来说应该粒子的取值为0,并且目标函数值为0为最佳,但我的适应度函数为1/(1+目标函数值),那不就导致了最后的最佳适应度值应该为1?
2.但是问题是我的TCPSO中粒子却确实越来越大,这导致了我的目标函数值越来越大,而我的适应度函数为1/(1+目标函数值)趋向于为0,但还是和0不相等。
以下是我提供的主程序、目标函数程序、适应度程序、TCPSO程序、以及文章结果呈现
程序如下matlab
clc;
clear;
% 初始化种群
M = 80; % 种群规模
D = 10; % 维度
X_min = -10; % 最小值
X_max = 10; % 最大值
max_iter = 100; % 最大迭代次数
% 初始化Tent混沌序列
tent_sequences = generate_tent_population(M, D);
% 将混沌序列映射至解空间
positions = X_min + (X_max - X_min) * tent_sequences;
% 反向学习策略
K = rand(size(positions)); % 生成随机数K
OP = K .* (X_min - X_max) - positions; % 计算反向解
% 选择适应度较好的前N个解作为初始种群
O = floor(M / 2);
fitness_values = calculate_fitness([positions; OP]); % 计算所有解的适应度
[~, sorted_indices] = sort(fitness_values, 'descend'); % 排序
best_Indices = sorted_indices(1:O);
New_group = [positions; OP];
initial_population = New_group(best_Indices, :); % 生成初始种群
% 确定A群和P群的规模
population_size_A = floor(O / 2);
population_size_P = O - population_size_A;
% 将初始种群分为A群和P群
index = randperm(O); % 随机排列种群个体的索引
index_A = index(1:population_size_A); % A群的个体索引
index_P = index(population_size_A+1:end); % B群的个体索引
% 使用索引划分种群
population_A = initial_population(index_A, :);
population_P = initial_population(index_P, :);
% 对population_A和population_P进行规范化
population_A = max(min(population_A, X_max), X_min);
population_P = max(min(population_P, X_max), X_min);
% 输出A群和P群
disp('Population A:');
disp(population_A);
disp('Population P:');
disp(population_P);
% 初始化最优解
A_best = initial_population(1, :); % TCABC算法的最优解,选取初始种群中的一个解
G_best = initial_population(1, :); % TCPSO算法的全局最优解,选取初始种群中的一个解
F_A_best = calculate_fitness(A_best); % TCABC算法的最优解的适应度值
F_G_best = calculate_fitness(G_best); % TCPSO算法的全局最优解的适应度值
% 主循环
for iter = 1:max_iter
% 调用TCABC算法
[A_best, F_A_best] = TCABC(population_A,A_best);
if iter == 1
isFirstGen = true;
else
isFirstGen = false;
end
% 调用TCPSO算法
[G_best, F_G_best] = TCPSO(population_P,G_best,isFirstGen);
% 使用重组算子生成新的最优解
Best = recombination_operator(A_best, G_best, F_A_best, F_G_best);
% 更新TCABC和TCPSO的最优解
if iter < max_iter
A_best = Best;
G_best = Best;
end
% 输出当前迭代的最优解
fprintf('Iteration %d: Best Fitness = %f\n', iter, min(F_A_best, F_G_best));
end
% 输出最终的最优解及其适应度值
if F_A_best < F_G_best
Real_Best = A_best;
Real_F_Best = F_A_best;
else
Real_Best = G_best;
Real_F_Best = F_G_best;
end
disp('Final Best Solution:');
disp(Real_Best);
disp('Final Best Fitness:');
disp(Real_F_Best);
function initial_population = generate_tent_population(M, D)
% M: 种群规模
% D: 维度
% 初始化种群
initial_population = zeros(M, D);
% 生成初始随机种群在 [0, 1] 间的随机数
for i = 1:M
for d = 1:D
initial_population(i, d) = rand();
end
end
% 进行 Tent 混沌映射迭代
num_iterations = 1; % 这里只需迭代一次,根据需要调整
for t = 1:num_iterations
for i = 1:M
for d = 1:D
Z_k_d_t = initial_population(i, d);
if Z_k_d_t < 0.7
Z_k_d_t1 = Z_k_d_t / 0.7;
else
Z_k_d_t1 = (10 * (1 - Z_k_d_t)) / 3;
end
initial_population(i, d) = Z_k_d_t1;
end
end
end
end
function Best = recombination_operator(A_best, G_best, F_A_best, F_G_best)
% 获取维数
D = length(A_best);
% 计算选择概率 P_best
P_best = F_A_best / (F_G_best + F_A_best);
% 初始化最优解 Best
Best = zeros(1, D);
% 为每一维产生随机数,并选择对应的最优值
for d = 1:D
r = rand();
if r <= P_best
Best(d) = A_best(d);
else
Best(d) = G_best(d);
end
end
end
function f_val = objective_function(individual)
% 示例目标函数:Sphere函数
f_val = sum(individual .^ 2);
end
function fitness = calculate_fitness(population)
% 计算适应度值
num_individuals = size(population, 1);
fitness = zeros(num_individuals, 1);
for i = 1:num_individuals
f_val = objective_function(population(i, :));
if f_val >= 0
fitness(i) = 1 / (1 + f_val);
else
fitness(i) = 1 + abs(f_val);
end
end
end
function [A_best, F_A_best] = TCABC(population_A,Best)
% Step1 : 初始化参数
NP = 50; % 蜂群大小
foodnumber = NP/2; % 蜜源数量
D = 10; % 解的维度
X_min = -10 * ones(1, D); % 解空间最小值
X_max = 10 * ones(1, D); % 解空间最大值
Limit = 100; % 同一蜜源被限制次数
max_iter = 10; % 最大迭代次数
iter = 0; % 初始化迭代次数
% Step2 : 把通过混沌反向学习得出的种群中的A种群当作初始蜜源位置
Initial_Foods = population_A;
% Step3 : 计算适应度,筛选出初始蜜源
Initial_Fitness = calculate_fitness(Initial_Foods); %计算适应度值
% 筛选出初始蜜源位置
O = floor(foodnumber / 2); % 选择前O个蜜源位置
[~, sorted_Indices] = sort(Initial_Fitness, 'descend');
best_Indices = sorted_Indices(1:O);
Initial_Foods = Initial_Foods(best_Indices, :); % 筛选出最佳蜜源位置,即初始蜜源位置
Initial_Fitness = Initial_Fitness(best_Indices); % 筛选出最佳蜜源位置的适应度值,即最佳的适应度值
trial = zeros(O, 1); % 初始化蜜源位置的试验计数
% 预设值
F_A_best = -Inf;
A_best = zeros(O, 1);
% 开始迭代
while iter < max_iter
iter = iter + 1;
% Step4、5 : 采蜜蜂阶段并更新个体
for i = 1:O
% 参数随机可变
Param1Change = fix(rand * D) + 1;
% 随机选择一个参数进行变化,生成一个介于 1 和 D 之间的整数,表示选择哪个维度进行变化。
neighbour = fix(rand * O) + 1;
% 随机选择另一个食物源作为邻居,生成一个介于 1 和 foodnumber 之间的整数,表示选择哪个邻居食物源。
while neighbour == i
neighbour = fix(rand * O) + 1; % 确保 neighbour 不等于 i。
end
sol = Initial_Foods(i, :); % 选择上一代中的第 i 个个体
sol(Param1Change) = Initial_Foods(i, Param1Change) + (Initial_Foods(i, Param1Change) - Initial_Foods(neighbour, Param1Change)) * (rand - 0.5) * 2;
% 使用当前解 i 和随机选择的邻居解之间的差值进行更新,(rand - 0.5) * 2 生成一个在 [-1, 1] 之间的随机数。
% 个体取值范围约束
ind = find(sol < X_min); % 最小值约束
sol(ind) = X_min(ind);
ind = find(sol > X_max); % 最大值约束
sol(ind) = X_max(ind);
% 估计新的目标函数值和适应度值
FitnessSol = calculate_fitness(sol);
% 更新最优个体值
if FitnessSol > Initial_Fitness(i) % 如果新产生的个体值适应度值越大,则表明函数值越小,则个体最优
Initial_Foods(i, :) = sol;
Initial_Fitness(i) = FitnessSol;
trial(i) = 0;
else
trial(i) = trial(i) + 1; % 如果解 i 不能改善,增加其试验计数,即拖尾数+1
end
end
% Step6、7 : 观望蜂阶段并更新个体,记录最佳位置与适应度值
for i = 1:O
% 锦标赛选择策略,初始化得分数组
scores = zeros(O, 1);
% 随机选取两个个体进行适应度比较,并对适应度较大的个体加1分
for j = 1:O
candidates = randperm(O, 2); % 随机选择两个个体
if Initial_Fitness(candidates(1)) > Initial_Fitness(candidates(2))
scores(candidates(1)) = scores(candidates(1)) + 1;
else
scores(candidates(2)) = scores(candidates(2)) + 1;
end
end
% 确保至少每个个体都参与一轮
for j = 1:O
if scores(j) == 0
% 若该个体未得分,则进行一次自我比较,确保至少参与一轮
scores(j) = scores(j) + 1;
end
end
% 计算每个蜜源被选择的概率
probabilities = scores / sum(scores);
% 按概率选择一个蜜源
selected = find(rand <= cumsum(probabilities), 1);
Param2Change = fix(rand * D) + 1; % 随机选择一个参数进行变化
if iter == 1
neighbour_index = fix(rand * O) + 1;
while neighbour_index == selected
neighbour_index = fix(rand * O) + 1;
end
neighbour = Initial_Foods(neighbour_index, :); % 确保 neighbour 是一个向量
else
neighbour = Best; % 使用重组算子产生的最佳解 Best 作为邻居
end
sol = Initial_Foods(selected, :);
sol(Param2Change) = Initial_Foods(selected, Param2Change) + ...
(Initial_Foods(selected, Param2Change) - neighbour(Param2Change)) * (rand - 0.5) * 2;
% 个体取值范围约束
ind = find(sol < X_min);
sol(ind) = X_min(ind);
ind = find(sol > X_max);
sol(ind) = X_max(ind);
% 估计新的目标函数值和适应度值
FitnessSol = calculate_fitness(sol);
% 更新最优个体值
if FitnessSol > Initial_Fitness(selected)
Initial_Foods(selected, :) = sol;
Initial_Fitness(selected) = FitnessSol;
trial(selected) = 0;
else
trial(selected) = trial(selected) + 1;
end
end
% Step8 : 侦察蜂阶段
for i = 1:O
if trial(i) > Limit
tent_sequence = rand(1, D); % 生成一个随机向量
for j = 1:10 % 使用Tent混沌映射进行多次迭代
tent_sequence = arrayfun(@tent_map, tent_sequence);
end
Initial_Foods(i, :) = X_min + (X_max - X_min) .* tent_sequence; % 将Tent混沌序列映射到解空间范围内
Initial_Fitness = calculate_fitness(Initial_Foods);
trial(i) = 0;
end
end
% Step9 : 记录全局最佳蜜源和适应度值
[best_fitness, best_index] = max(Initial_Fitness);
best_food = Initial_Foods(best_index, :);
%判断是否需要更新全局最佳
if iter == 1 || best_fitness > F_A_best
F_A_best = best_fitness;
A_best = best_food;
end
end
fprintf('A_best : %s\n', mat2str(A_best));
fprintf('F_A_best : %f\n', F_A_best);
end
function [G_Best, F_G_best] = TCPSO(population_P,Best,isFirstGen)
% Step1 : 初始化算法相关参数
N = 15; % 选取适应度较好的个体数量
D = 10; % 粒子维数
X_min = -1000000; % 各维的取值范围
X_max = 1000000;
C1 = 1.5; % 学习因子
C2 = 1.5;
max_iter = 100; % 最大迭代次数
max_velocity = (X_max - X_min) / 10; % 最大速度限制
w_max = 0.9; % 最大惯性权重
w_min = 0.4; % 最小惯性权重
% Step2 : 输入population_P作为若干初始蜜源
positions = population_P;
% Step3 : 计算粒子适应度值, 选取适应度较好的N个位置作为初始位置, 并随机产生N个初始速度
fitness_values = calculate_fitness(positions); %计算适应度值
[~, sorted_indices] = sort(fitness_values); % 按适应度排序
positions1 = positions(sorted_indices(1:N), :); % 选取适应度较好的N个位置,即初始位置
velocities = (X_max - X_min) .* (rand(N, D) - 0.5) * 0.1; % 生成N个初始速度
% Step4-5 : 更新群体最佳个体及适应度,更新最佳个体及适应度
fitness_values1 = calculate_fitness(positions1); %计算适应度值
[best_fitness,idx] = min(fitness_values1); % 计算出初始位置的适应度值的最小值与索引
if isFirstGen
F_G_best = best_fitness; % 初代群体位置最优适应度
G_Best = positions1(idx, :); % 初代群体最优个体
else
F_G_best = calculate_fitness(Best);
G_Best = Best;
end
best_positions = positions1; % 每个粒子在搜索过程中的历史最佳位置矩阵
fitness_best = fitness_values1; % 个体最佳适应度
% Step6 : 更新粒子位置和速度
for i = 1 : max_iter
% 动态调整惯性权重
W = w_max - (w_max - w_min) * i / max_iter;
for j = 1 : N
% 速度更新并限制在最大速度范围内
velocities(j,:) =W * velocities(j,:) + C1 * rand * (best_positions(j,:) - positions1(j,:))...
+ C2 * rand *(G_Best - positions1(j,:));
velocities(j,:) = max(min(velocities(j,:), max_velocity), -max_velocity);
% 位置更新
positions1(j,:) = positions1(j,:) + velocities(j,:);
positions1(j,positions1(j,:) > X_max) = X_max;
positions1(j,positions1(j,:) < X_min) = X_min;
% 适应度值更新
fitness_values1(j) = calculate_fitness(positions1(j,:));
% 更新个体最优位置
if fitness_values1(j) < fitness_best(j)
best_positions(j,:) = positions1(j,:);
fitness_best(j) = calculate_fitness(positions1(j,:));
end
% 更新全局最优位置
if fitness_values1(j) < F_G_best
F_G_best = fitness_values1(j);
G_Best = positions1(j,:);
end
end
% Step7 : 针对当前最优位置Global_best_positions, 利用Tent混沌搜索产生最优新解Gbest
tent_Global_best_positions = generate_tent_population(1, D);
tent_G_best_positions = X_min + (X_max - X_min) * tent_Global_best_positions; % 将Tent混沌序列映射到粒子位置范围内
tent_G_best_fitness = calculate_fitness(tent_G_best_positions); %计算适应度值
% Step8 : 利用tent_G_best_positions替代种群任意一粒子的位置,作用:增加种群的变异性,使算法更容易跳出局部最优解,找到更好的全局最优解。
if tent_G_best_fitness < F_G_best
G_Best = tent_G_best_positions;
F_G_best = tent_G_best_fitness;
end
% 替代种群任意一粒子的位置
replace_idx = randi(N);
positions1(replace_idx, :) = tent_G_best_positions; % positions1为当代种群
fitness_values1(replace_idx) = tent_G_best_fitness; % fitness_values1为当代适应度值
% 检查停止条件
if F_G_best < 1e-6 % 假设阈值1e-6
break;
end
end
% 输出最佳解和最佳适应度值
fprintf('G_Best : %s\n', mat2str(G_Best));
fprintf('F_G_best: %f\n', F_G_best);
end
以及文章的结果图片
论文为 Tent混沌人工蜂群与粒子群混合算法 匡芳君